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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Generated from package.json and package-lock.json; do not edit. */
|
|
2
2
|
export const PACKAGE_METADATA = {
|
|
3
3
|
name: "rea-agents",
|
|
4
|
-
version: "
|
|
5
|
-
serverSdkVersion: "2.0.0
|
|
6
|
-
clientSdkVersion: "2.0.0
|
|
7
|
-
coreSdkVersion: "2.0.0
|
|
4
|
+
version: "3.0.0", // x-release-please-version
|
|
5
|
+
serverSdkVersion: "2.0.0",
|
|
6
|
+
clientSdkVersion: "2.0.0",
|
|
7
|
+
coreSdkVersion: "2.0.0",
|
|
8
8
|
skillVersion: "23",
|
|
9
9
|
};
|
|
@@ -17,4 +17,4 @@ export const GHIDRA_MAX_QUEUED_REQUESTS = 32;
|
|
|
17
17
|
/** Maximum encoded response line accepted from the Java bridge. */
|
|
18
18
|
export const GHIDRA_MAX_LINE_BYTES = 1024 * 1024;
|
|
19
19
|
/** Version of REA's Java bridge handshake and request protocol. */
|
|
20
|
-
export const GHIDRA_BRIDGE_VERSION =
|
|
20
|
+
export const GHIDRA_BRIDGE_VERSION = 6;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AnalysisInputError, AnalysisOutputError } from "../domain/errors.js";
|
|
3
|
-
import { functionDossierSchema, } from "../domain/hopperValues.js";
|
|
3
|
+
import { functionInstructionWindowSchema, functionDossierSchema, } from "../domain/hopperValues.js";
|
|
4
4
|
import { jsonObjectSchema, jsonValueSchema, } from "../domain/jsonValue.js";
|
|
5
|
+
import { nativeApiBoundarySchema } from "../domain/nativeApiBoundary.js";
|
|
5
6
|
import { err, ok } from "../domain/result.js";
|
|
6
7
|
import { ghidraBoundedIdentifierSchema, ghidraCanonicalAddressSchema, } from "./GhidraInventoryValues.js";
|
|
7
8
|
/** Read-only function operations admitted by the Ghidra adapter. */
|
|
@@ -12,6 +13,7 @@ export const GHIDRA_FUNCTION_OPERATIONS = [
|
|
|
12
13
|
"procedure_callers",
|
|
13
14
|
"procedure_info",
|
|
14
15
|
"procedure_pseudo_code",
|
|
16
|
+
"read_function_instructions",
|
|
15
17
|
"procedure_references",
|
|
16
18
|
"xrefs",
|
|
17
19
|
];
|
|
@@ -66,6 +68,13 @@ const inputSchemas = {
|
|
|
66
68
|
procedure_callers: z.object(directProcedure).strict(),
|
|
67
69
|
procedure_info: z.object(directProcedure).strict(),
|
|
68
70
|
procedure_pseudo_code: z.object(directProcedure).strict(),
|
|
71
|
+
read_function_instructions: z
|
|
72
|
+
.object({
|
|
73
|
+
...directProcedure,
|
|
74
|
+
offset: z.number().int().min(0).max(100_000).default(0),
|
|
75
|
+
limit: z.number().int().min(1).max(500).default(64),
|
|
76
|
+
})
|
|
77
|
+
.strict(),
|
|
69
78
|
procedure_references: z
|
|
70
79
|
.object({
|
|
71
80
|
...directProcedure,
|
|
@@ -183,7 +192,32 @@ const procedureInfo = z
|
|
|
183
192
|
classification,
|
|
184
193
|
})
|
|
185
194
|
.strict();
|
|
186
|
-
const
|
|
195
|
+
const ghidraNativeApiBoundary = nativeApiBoundarySchema.superRefine((value, context) => {
|
|
196
|
+
if (!value.available)
|
|
197
|
+
return;
|
|
198
|
+
if (value.provenance !== "ghidra-high-function")
|
|
199
|
+
context.addIssue({
|
|
200
|
+
code: "custom",
|
|
201
|
+
message: "Ghidra native API observations require HighFunction provenance",
|
|
202
|
+
});
|
|
203
|
+
const addresses = value.jump_tables.flatMap((table) => [
|
|
204
|
+
table.dispatch_address,
|
|
205
|
+
...table.data_sources.map(({ address }) => address),
|
|
206
|
+
...table.mappings.flatMap(({ target_address, data_addresses }) => [
|
|
207
|
+
target_address,
|
|
208
|
+
...data_addresses,
|
|
209
|
+
]),
|
|
210
|
+
]);
|
|
211
|
+
if (addresses.some((address) => !ghidraCanonicalAddressSchema.safeParse(address).success))
|
|
212
|
+
context.addIssue({
|
|
213
|
+
code: "custom",
|
|
214
|
+
message: "Ghidra native API observation contains a non-canonical address",
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
const ghidraFunctionDossier = functionDossierSchema
|
|
218
|
+
.extend({ native_api: ghidraNativeApiBoundary })
|
|
219
|
+
.strict()
|
|
220
|
+
.superRefine((value, context) => {
|
|
187
221
|
const addresses = [
|
|
188
222
|
value.procedure.address,
|
|
189
223
|
...value.comments.items.map(({ address }) => address),
|
|
@@ -235,6 +269,9 @@ const ghidraFunctionDossier = functionDossierSchema.superRefine((value, context)
|
|
|
235
269
|
message: "Ghidra dossier omitted required uncertainty limitations",
|
|
236
270
|
});
|
|
237
271
|
});
|
|
272
|
+
const ghidraFunctionInstructionWindow = functionInstructionWindowSchema
|
|
273
|
+
.extend({ procedure: procedureIdentity })
|
|
274
|
+
.strict();
|
|
238
275
|
const resultSchemas = {
|
|
239
276
|
analyze_function: ghidraFunctionDossier,
|
|
240
277
|
procedure_assembly: z.string(),
|
|
@@ -242,6 +279,7 @@ const resultSchemas = {
|
|
|
242
279
|
procedure_callers: z.array(ghidraCanonicalAddressSchema),
|
|
243
280
|
procedure_info: procedureInfo,
|
|
244
281
|
procedure_pseudo_code: z.string().nullable(),
|
|
282
|
+
read_function_instructions: ghidraFunctionInstructionWindow,
|
|
245
283
|
procedure_references: procedureReferences,
|
|
246
284
|
xrefs: z.array(ghidraCanonicalAddressSchema),
|
|
247
285
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
|
|
2
2
|
import { GHIDRA_DECOMPILE_REQUEST_TIMEOUT_MS, GHIDRA_MAX_LINE_BYTES, GHIDRA_REQUEST_TIMEOUT_MS, } from "./GhidraDefaults.js";
|
|
3
3
|
import { GHIDRA_FUNCTION_OPERATIONS } from "./GhidraFunctionValues.js";
|
|
4
4
|
import { GHIDRA_INVENTORY_OPERATIONS } from "./GhidraInventoryValues.js";
|
|
@@ -8,10 +8,7 @@ export const GHIDRA_PROVIDER_IDENTITY = Object.freeze({
|
|
|
8
8
|
name: "Ghidra",
|
|
9
9
|
version: null,
|
|
10
10
|
});
|
|
11
|
-
const providerContractByName = new Map(
|
|
12
|
-
contract.name,
|
|
13
|
-
contract,
|
|
14
|
-
]));
|
|
11
|
+
const providerContractByName = new Map(GENERATED_MCP_TOOL_CATALOG.filter(({ kind }) => kind === "official-proxy" || kind === "enhanced").map((contract) => [contract.name, contract]));
|
|
15
12
|
/** Provider-neutral read-only contracts implemented by the Ghidra adapter. */
|
|
16
13
|
export const GHIDRA_PROVIDER_TOOL_CONTRACTS = Object.freeze([...GHIDRA_INVENTORY_OPERATIONS, ...GHIDRA_FUNCTION_OPERATIONS].map((operation) => {
|
|
17
14
|
const contract = providerContractByName.get(operation);
|
|
@@ -26,6 +23,7 @@ const PAGINATED_OPERATIONS = new Set([
|
|
|
26
23
|
"search_procedures",
|
|
27
24
|
"search_strings",
|
|
28
25
|
"procedure_references",
|
|
26
|
+
"read_function_instructions",
|
|
29
27
|
"analyze_function",
|
|
30
28
|
]);
|
|
31
29
|
const SEARCH_OPERATIONS = new Set([
|
|
@@ -93,6 +91,12 @@ export const limitationsFor = (operation) => {
|
|
|
93
91
|
"Pseudocode is Ghidra decompiler output, not original source and not text-equivalent to Hopper output; each decompile has a 30-second native deadline.",
|
|
94
92
|
"External functions and functions without an analyzable body return null; other decompiler failures remain explicit.",
|
|
95
93
|
];
|
|
94
|
+
case "read_function_instructions":
|
|
95
|
+
return [
|
|
96
|
+
...common,
|
|
97
|
+
"This bounded fast path reads only the requested function instruction window and does not invoke the decompiler or whole-program string/name inventories.",
|
|
98
|
+
"Instruction text is Ghidra-specific and does not claim textual equivalence with Hopper output.",
|
|
99
|
+
];
|
|
96
100
|
case "procedure_assembly":
|
|
97
101
|
return [
|
|
98
102
|
...common,
|
|
@@ -130,39 +134,44 @@ export const limitationsFor = (operation) => {
|
|
|
130
134
|
}
|
|
131
135
|
};
|
|
132
136
|
/** Provider-neutral capabilities advertised by every non-Windows Ghidra session. */
|
|
133
|
-
export const CAPABILITIES = Object.freeze(GHIDRA_PROVIDER_TOOL_CONTRACTS.map((contract) =>
|
|
134
|
-
|
|
135
|
-
operation
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
137
|
+
export const CAPABILITIES = Object.freeze(GHIDRA_PROVIDER_TOOL_CONTRACTS.map((contract) => {
|
|
138
|
+
const operation = contract.analysisOperation;
|
|
139
|
+
if (operation === null)
|
|
140
|
+
throw new TypeError(`Missing analysis operation for ${contract.name}`);
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
provider: GHIDRA_PROVIDER_IDENTITY,
|
|
143
|
+
operation,
|
|
144
|
+
inputContractVersion: 1,
|
|
145
|
+
outputContractVersion: 1,
|
|
146
|
+
available: true,
|
|
147
|
+
reason: null,
|
|
148
|
+
pagination: PAGINATED_OPERATIONS.has(contract.name)
|
|
149
|
+
? "offset"
|
|
150
|
+
: "none",
|
|
151
|
+
exhaustive: !PAGINATED_OPERATIONS.has(contract.name),
|
|
152
|
+
effects: Object.freeze({
|
|
153
|
+
mutatesArtifact: false,
|
|
154
|
+
launchesProcess: true,
|
|
155
|
+
mayShowUi: false,
|
|
156
|
+
mayAccessNetwork: false,
|
|
157
|
+
mayWriteFilesystem: true,
|
|
158
|
+
changesPermissions: false,
|
|
159
|
+
requiresRoot: false,
|
|
160
|
+
}),
|
|
161
|
+
limits: Object.freeze({
|
|
162
|
+
maxResults: PAGINATED_OPERATIONS.has(contract.name)
|
|
163
|
+
? SEARCH_OPERATIONS.has(contract.name)
|
|
164
|
+
? 100
|
|
165
|
+
: 500
|
|
166
|
+
: null,
|
|
167
|
+
maxPayloadBytes: GHIDRA_MAX_LINE_BYTES,
|
|
168
|
+
timeoutMs: DECOMPILE_OPERATIONS.has(contract.name)
|
|
169
|
+
? GHIDRA_DECOMPILE_REQUEST_TIMEOUT_MS
|
|
170
|
+
: GHIDRA_REQUEST_TIMEOUT_MS,
|
|
171
|
+
}),
|
|
172
|
+
limitations: Object.freeze(limitationsFor(contract.name)),
|
|
173
|
+
});
|
|
174
|
+
}));
|
|
166
175
|
/** Capabilities advertised for the experimental Windows x64 P0 boundary. */
|
|
167
176
|
export const WINDOWS_P0_CAPABILITIES = Object.freeze(CAPABILITIES.map((capability) => Object.freeze({
|
|
168
177
|
...capability,
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { HopperProcessError } from "../domain/errors.js";
|
|
2
|
+
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
|
3
|
+
import { err, ok } from "../domain/result.js";
|
|
4
|
+
import { createOwnedHopperShutdownDiagnostic, providerCleanupFailure, } from "./HopperDiagnostics.js";
|
|
5
|
+
import { isHopperCleanupRequired, isHopperShutdownAcknowledgement, } from "./HopperSessionValues.js";
|
|
6
|
+
/** Close Hopper phases and retain every resource whose cleanup is unverified. */
|
|
7
|
+
export const cleanupHopperSession = async (input) => {
|
|
8
|
+
const state = {
|
|
9
|
+
issues: [],
|
|
10
|
+
resources: new Set(),
|
|
11
|
+
cleanupResult: undefined,
|
|
12
|
+
shutdownConfirmed: false,
|
|
13
|
+
ownedProcessStopped: false,
|
|
14
|
+
};
|
|
15
|
+
await report(input.progress, 0, "requesting Hopper document shutdown");
|
|
16
|
+
await requestShutdown(input, state);
|
|
17
|
+
await report(input.progress, 0.35, "releasing Hopper bridge transport");
|
|
18
|
+
input.releaseTransport(input.socket);
|
|
19
|
+
await stopProcess(input, state);
|
|
20
|
+
recordUnconfirmedDocument(input, state);
|
|
21
|
+
await report(input.progress, 0.75, "removing Hopper private runtime files");
|
|
22
|
+
await closeRuntimeRoot(input.runtimeRoot, state);
|
|
23
|
+
return cleanupOutcome(input, state);
|
|
24
|
+
};
|
|
25
|
+
const requestShutdown = async (input, state) => {
|
|
26
|
+
if (input.socket === undefined ||
|
|
27
|
+
input.socket.destroyed ||
|
|
28
|
+
input.activeRequest !== null) {
|
|
29
|
+
if (input.activeRequest !== null)
|
|
30
|
+
input.logger.warn({
|
|
31
|
+
method: input.activeRequest.operation,
|
|
32
|
+
callerState: input.activeRequest.callerState,
|
|
33
|
+
}, "Hopper shutdown skipped because a bridge operation remained active");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const shutdown = await input
|
|
37
|
+
.request("shutdown")
|
|
38
|
+
.catch(() => err(new HopperProcessError(null)));
|
|
39
|
+
if (shutdown.ok &&
|
|
40
|
+
isHopperCleanupRequired(shutdown.value) &&
|
|
41
|
+
input.launch?.shutdownByCleanup === true &&
|
|
42
|
+
input.launch.cleanup !== undefined) {
|
|
43
|
+
state.cleanupResult = await input.launch
|
|
44
|
+
.cleanup()
|
|
45
|
+
.catch(providerCleanupFailure);
|
|
46
|
+
if (!state.cleanupResult.cleaned) {
|
|
47
|
+
state.shutdownConfirmed = await fallbackDocumentShutdown(input);
|
|
48
|
+
state.cleanupResult = await input.launch
|
|
49
|
+
.cleanup()
|
|
50
|
+
.catch(providerCleanupFailure);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (shutdown.ok) {
|
|
54
|
+
state.shutdownConfirmed = isHopperShutdownAcknowledgement(shutdown.value);
|
|
55
|
+
}
|
|
56
|
+
if (!shutdown.ok ||
|
|
57
|
+
(!state.shutdownConfirmed && state.cleanupResult === undefined))
|
|
58
|
+
input.logger.warn({ status: shutdown.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown was not confirmed");
|
|
59
|
+
};
|
|
60
|
+
const fallbackDocumentShutdown = async (input) => {
|
|
61
|
+
const fallback = await input
|
|
62
|
+
.request("shutdown_document")
|
|
63
|
+
.catch(() => err(new HopperProcessError(null)));
|
|
64
|
+
const confirmed = fallback.ok && isHopperShutdownAcknowledgement(fallback.value);
|
|
65
|
+
if (!confirmed)
|
|
66
|
+
input.logger.warn({ status: fallback.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown fallback was not confirmed");
|
|
67
|
+
return confirmed;
|
|
68
|
+
};
|
|
69
|
+
const stopProcess = async (input, state) => {
|
|
70
|
+
const supervisor = input.processSupervisor;
|
|
71
|
+
if (supervisor === undefined)
|
|
72
|
+
return;
|
|
73
|
+
const stopped = await supervisor.stop(state.cleanupResult === undefined
|
|
74
|
+
? {}
|
|
75
|
+
: { cleanupResult: state.cleanupResult });
|
|
76
|
+
const diagnostic = createOwnedHopperShutdownDiagnostic(supervisor.launch, stopped, state.cleanupResult);
|
|
77
|
+
try {
|
|
78
|
+
input.onDiagnostic?.(diagnostic);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Diagnostic consumers cannot change the already-observed cleanup result.
|
|
82
|
+
}
|
|
83
|
+
input.logger.info(diagnostic, "Owned Hopper launcher shutdown completed");
|
|
84
|
+
if (stopped.status !== "incomplete") {
|
|
85
|
+
state.ownedProcessStopped = stopped.status !== "not-owned";
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const processGroupId = supervisor.launch.ownership?.processGroupId;
|
|
89
|
+
const resource = processGroupId === undefined
|
|
90
|
+
? "hopper-process"
|
|
91
|
+
: `process-group:${String(processGroupId)}`;
|
|
92
|
+
state.resources.add(resource);
|
|
93
|
+
state.issues.push({ resource, reason: stopped.reason });
|
|
94
|
+
input.logger.warn({ reason: stopped.reason }, "Owned launcher cleanup failed closed");
|
|
95
|
+
};
|
|
96
|
+
const recordUnconfirmedDocument = (input, state) => {
|
|
97
|
+
if ((input.socket === undefined && input.launch === undefined) ||
|
|
98
|
+
state.shutdownConfirmed ||
|
|
99
|
+
state.ownedProcessStopped)
|
|
100
|
+
return;
|
|
101
|
+
state.resources.add("hopper-document");
|
|
102
|
+
state.issues.push({
|
|
103
|
+
resource: "hopper-document",
|
|
104
|
+
reason: input.activeRequest === null
|
|
105
|
+
? "authenticated shutdown acknowledgement was not observed"
|
|
106
|
+
: `bridge operation ${input.activeRequest.operation} remained active after caller ${input.activeRequest.callerState}`,
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
const closeRuntimeRoot = async (runtimeRoot, state) => {
|
|
110
|
+
try {
|
|
111
|
+
await runtimeRoot?.close();
|
|
112
|
+
}
|
|
113
|
+
catch (cause) {
|
|
114
|
+
const resource = runtimeRoot?.path ?? "hopper-runtime-root";
|
|
115
|
+
state.resources.add(resource);
|
|
116
|
+
state.issues.push({
|
|
117
|
+
resource,
|
|
118
|
+
reason: cause instanceof Error
|
|
119
|
+
? cause.message
|
|
120
|
+
: "private runtime root cleanup failed",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const cleanupOutcome = (input, state) => {
|
|
125
|
+
if (state.issues.length === 0)
|
|
126
|
+
return ok(null);
|
|
127
|
+
return err(new ProviderCleanupError("hopper", [...state.resources], {
|
|
128
|
+
issues: cleanupIssueDetails(state.issues),
|
|
129
|
+
...(input.runtimeRoot === undefined
|
|
130
|
+
? {}
|
|
131
|
+
: { runtime_root: input.runtimeRoot.path }),
|
|
132
|
+
...(input.activeRequest === null
|
|
133
|
+
? {}
|
|
134
|
+
: { active_request: activityDetails(input.activeRequest) }),
|
|
135
|
+
}));
|
|
136
|
+
};
|
|
137
|
+
const cleanupIssueDetails = (issues) => issues.map((issue) => ({
|
|
138
|
+
resource: issue.resource,
|
|
139
|
+
reason: issue.reason,
|
|
140
|
+
}));
|
|
141
|
+
const activityDetails = (activity) => ({
|
|
142
|
+
request_id: activity.requestId,
|
|
143
|
+
operation: activity.operation,
|
|
144
|
+
elapsed_ms: activity.elapsedMs,
|
|
145
|
+
timeout_ms: activity.timeoutMs,
|
|
146
|
+
caller_state: activity.callerState,
|
|
147
|
+
queued_requests: activity.queuedRequests,
|
|
148
|
+
});
|
|
149
|
+
const report = async (progress, completed, message) => {
|
|
150
|
+
await progress
|
|
151
|
+
?.report({
|
|
152
|
+
phase: "hopper_cleanup",
|
|
153
|
+
completed,
|
|
154
|
+
total: 1,
|
|
155
|
+
message,
|
|
156
|
+
})
|
|
157
|
+
.catch(() => undefined);
|
|
158
|
+
};
|