rea-agents 2.5.0 → 3.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.
Files changed (253) hide show
  1. package/README.md +20 -12
  2. package/bridge/ghidra/ReaGhidraBridge.java +477 -4
  3. package/bridge/hopper_bridge.py +54 -4
  4. package/dist/application/AnalysisContextQueries.js +142 -0
  5. package/dist/application/AnalysisSnapshotCache.js +4 -2
  6. package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
  7. package/dist/application/ArtifactInventory/policy.js +17 -0
  8. package/dist/application/ArtifactInventory/reader.js +1 -4
  9. package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
  10. package/dist/application/ArtifactInventory/scanReader.js +7 -7
  11. package/dist/application/ArtifactInventory/types.js +1 -5
  12. package/dist/application/BinarySession.js +19 -20
  13. package/dist/application/BinarySessionComposition.js +21 -0
  14. package/dist/application/BinarySessionRecords.js +106 -10
  15. package/dist/application/BinarySessionStatus.js +11 -5
  16. package/dist/application/BrowserEvidence.js +3 -5
  17. package/dist/application/CapabilityClientRequirements.js +26 -0
  18. package/dist/application/CapabilityInventory.js +140 -55
  19. package/dist/application/ClientRegistrationStatus.js +4 -1
  20. package/dist/application/CrossVersionInventory.js +7 -6
  21. package/dist/application/DirectAnalysis.js +6 -2
  22. package/dist/application/ElectronActiveEvidence.js +55 -0
  23. package/dist/application/ElectronActiveObservationPort.js +1 -0
  24. package/dist/application/ElectronActiveObservationService.js +81 -0
  25. package/dist/application/EnhancedTools.js +49 -17
  26. package/dist/application/EvidenceBundleCommands.js +5 -1
  27. package/dist/application/EvidenceLedger.js +53 -17
  28. package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
  29. package/dist/application/JavaScriptReplayPermission.js +1 -1
  30. package/dist/application/JavaScriptReplayService.js +23 -15
  31. package/dist/application/LazyAnalysisProvider.js +77 -0
  32. package/dist/application/LoopbackReplay.js +1 -1
  33. package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
  34. package/dist/application/NativeApiInspection.js +80 -0
  35. package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
  36. package/dist/application/ProcessCaptureLifecycle.js +5 -0
  37. package/dist/application/ProcessCli.js +2 -1
  38. package/dist/application/ProcessHarness.js +8 -3
  39. package/dist/application/ProcessNormalization.js +2 -1
  40. package/dist/application/ProjectPermissionStore.js +1 -0
  41. package/dist/application/ReferenceSourceImport.js +2 -2
  42. package/dist/application/SessionProviderRouter.js +6 -6
  43. package/dist/application/SetupClientConfiguration.js +10 -3
  44. package/dist/application/WindowsCapabilities.js +5 -4
  45. package/dist/application/runtime.js +26 -9
  46. package/dist/artifacts/ArtifactProvider.js +8 -10
  47. package/dist/artifacts/SafeOutputTree.js +7 -8
  48. package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
  49. package/dist/browser/CdpElectronInspection.js +3 -1
  50. package/dist/browser/JavaScriptRuntimeScope.js +5 -0
  51. package/dist/browser/PlaywrightBrowserScenarioProvider.js +8 -2
  52. package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
  53. package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
  54. package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
  55. package/dist/browser/PlaywrightScenarioSession.js +4 -4
  56. package/dist/browser/SensitiveTextCapture.js +1 -1
  57. package/dist/browser/V8InspectorCaptureProjection.js +1 -0
  58. package/dist/browser/V8InspectorProvider.js +3 -3
  59. package/dist/catalogIdentity.js +15 -9
  60. package/dist/cli/artifactCommands.js +5 -3
  61. package/dist/cli/coreAnalysisCommands.js +41 -0
  62. package/dist/cli/managedCommands.js +1 -1
  63. package/dist/cliApplicationCommands.js +2 -2
  64. package/dist/cliBrowserAdvancedCommands.js +11 -5
  65. package/dist/cliBrowserCommands.js +14 -7
  66. package/dist/cliCommandNames.js +2 -0
  67. package/dist/cliElectronCommands.js +46 -4
  68. package/dist/cliJavaScriptRuntimeCommands.js +14 -6
  69. package/dist/cliObservationOptions.js +4 -0
  70. package/dist/cliPolicyCommands.js +1 -0
  71. package/dist/config/browserScenario.js +77 -0
  72. package/dist/config/electronAutomation.js +35 -0
  73. package/dist/config/environment.js +6 -0
  74. package/dist/config/javascriptReplay.js +41 -0
  75. package/dist/config/managedRuntime.js +25 -0
  76. package/dist/config/parseConfig.js +56 -200
  77. package/dist/config/parsers.js +10 -1
  78. package/dist/config/passiveObservation.js +157 -0
  79. package/dist/config/processCapture.js +47 -0
  80. package/dist/contracts/applicationToolContracts.js +2 -5
  81. package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
  82. package/dist/contracts/artifactToolContracts.js +35 -37
  83. package/dist/contracts/browserToolContracts.js +2 -2
  84. package/dist/contracts/electronToolContracts.js +30 -1
  85. package/dist/contracts/enhancedInputs.js +21 -27
  86. package/dist/contracts/functionWorkflowToolContracts.js +29 -0
  87. package/dist/contracts/managedToolContracts.js +4 -9
  88. package/dist/contracts/managedWorkflowExamples.js +12 -9
  89. package/dist/contracts/managedWorkflowToolContracts.js +30 -27
  90. package/dist/contracts/nativeToolContracts.js +2 -3
  91. package/dist/contracts/promptContracts.js +14 -15
  92. package/dist/contracts/sessionToolSchemas.js +61 -0
  93. package/dist/contracts/toolContractExamples.js +4 -0
  94. package/dist/contracts/toolContractHelpers.js +23 -0
  95. package/dist/contracts/toolContracts.js +12 -67
  96. package/dist/contracts/toolEffects.js +19 -0
  97. package/dist/contracts/toolOutputSchemaGroups.js +66 -11
  98. package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
  99. package/dist/contracts/toolSchemaMetadata.js +128 -0
  100. package/dist/doctorRuntime.js +1 -1
  101. package/dist/domain/analysisErrorPresentation.js +8 -2
  102. package/dist/domain/analysisErrorProjection.js +1 -0
  103. package/dist/domain/androidApplication.js +2 -0
  104. package/dist/domain/appleApplication.js +2 -0
  105. package/dist/domain/binaryTarget.js +7 -5
  106. package/dist/domain/binaryTargetTypes.js +1 -0
  107. package/dist/domain/browserCaptureComparison.js +21 -69
  108. package/dist/domain/browserObservation.js +22 -9
  109. package/dist/domain/bytecodeProvider.js +177 -0
  110. package/dist/domain/callPath.js +3 -2
  111. package/dist/domain/conformancePackage.js +169 -0
  112. package/dist/domain/conformanceReplay.js +104 -0
  113. package/dist/domain/conformanceTrustGate.js +328 -0
  114. package/dist/domain/customProtocolCapture.js +137 -0
  115. package/dist/domain/electronActiveObservation.js +277 -0
  116. package/dist/domain/electronObservation.js +15 -11
  117. package/dist/domain/electronStaticAnalysisValues.js +4 -1
  118. package/dist/domain/eventProcessTree.js +217 -0
  119. package/dist/domain/evidenceBundle.js +47 -0
  120. package/dist/domain/functionComparisonNormalization.js +15 -8
  121. package/dist/domain/functionDossierEvidence.js +9 -4
  122. package/dist/domain/hopperStartupFailure.js +1 -1
  123. package/dist/domain/hopperValues.js +68 -68
  124. package/dist/domain/inputIssueProjection.js +11 -2
  125. package/dist/domain/investigationWorkspace.js +16 -15
  126. package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
  127. package/dist/domain/javascriptReplay.js +79 -63
  128. package/dist/domain/javascriptRuntimeObservation.js +1 -0
  129. package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
  130. package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
  131. package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
  132. package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
  133. package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
  134. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  135. package/dist/domain/javascriptSemanticAnalysis.js +8 -12
  136. package/dist/domain/javascriptSourceParser.js +15 -0
  137. package/dist/domain/javascriptStaticAnalysis.js +8 -12
  138. package/dist/domain/knownPageCoverage.js +15 -7
  139. package/dist/domain/mobileApplicationInvestigation.js +159 -0
  140. package/dist/domain/nativeApiBoundary.js +138 -0
  141. package/dist/domain/nodeRuntimeCharacterization.js +14 -13
  142. package/dist/domain/objcSwiftMetadata.js +150 -0
  143. package/dist/domain/packageAnalysis.js +123 -0
  144. package/dist/domain/peInspection.js +196 -0
  145. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  146. package/dist/domain/processCaptureValidation.js +7 -3
  147. package/dist/domain/processComparison.js +12 -7
  148. package/dist/domain/processObservation.js +5 -6
  149. package/dist/domain/processReactiveMatching.js +14 -7
  150. package/dist/domain/processReactiveTransition.js +9 -3
  151. package/dist/domain/processScenario.js +6 -3
  152. package/dist/domain/processTraceComparison.js +3 -2
  153. package/dist/domain/protocolCapture.js +245 -0
  154. package/dist/domain/reconstructionReadinessSchemas.js +30 -2
  155. package/dist/domain/referenceSourceImportParsing.js +2 -2
  156. package/dist/domain/replayMachineRuntime.js +5 -3
  157. package/dist/domain/sourceToBundleComparison.js +2 -2
  158. package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
  159. package/dist/domain/sourceToBundleSignals.js +7 -1
  160. package/dist/domain/staticRuntimeCorrelation.js +7 -5
  161. package/dist/domain/webBundleAnalysis.js +14 -14
  162. package/dist/domain/webCaptureDiff.js +15 -12
  163. package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
  164. package/dist/dotnet/ManagedStaticProvider.js +34 -5
  165. package/dist/generatedMcpToolCatalog.js +37 -0
  166. package/dist/generatedPackageMetadata.js +4 -4
  167. package/dist/ghidra/GhidraClient.js +1 -1
  168. package/dist/ghidra/GhidraClientStartup.js +1 -1
  169. package/dist/ghidra/GhidraDefaults.js +1 -1
  170. package/dist/ghidra/GhidraFunctionValues.js +44 -16
  171. package/dist/ghidra/GhidraInventoryValues.js +57 -47
  172. package/dist/ghidra/GhidraProvider.js +18 -10
  173. package/dist/ghidra/GhidraProviderCapabilities.js +45 -39
  174. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  175. package/dist/ghidra/protocol.js +19 -42
  176. package/dist/hopper/BridgeLauncher.js +3 -1
  177. package/dist/hopper/HopperAnalysisProfile.js +2 -4
  178. package/dist/hopper/HopperCleanup.js +5 -6
  179. package/dist/hopper/HopperClient.js +27 -3
  180. package/dist/hopper/HopperProvider.js +42 -44
  181. package/dist/hopper/HopperRequestQueue.js +32 -4
  182. package/dist/hopper/HopperResponseStream.js +2 -2
  183. package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
  184. package/dist/hopper/protocol.js +63 -21
  185. package/dist/main/reload.js +1 -6
  186. package/dist/main/state.js +0 -14
  187. package/dist/main/transport.js +31 -41
  188. package/dist/main.js +17 -13
  189. package/dist/mcpDoctor.js +4 -26
  190. package/dist/mcpStartupPolicy.js +14 -0
  191. package/dist/process/PrivateRuntimeRoot.js +17 -0
  192. package/dist/process/ProcessOwnership.js +64 -128
  193. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  194. package/dist/process/ProcessOwnershipObservation.js +88 -0
  195. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  196. package/dist/process/ProviderDeadline.js +8 -12
  197. package/dist/process/WindowsAuthority.js +32 -0
  198. package/dist/reference/ReferenceSourceReader.js +3 -3
  199. package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
  200. package/dist/replay/JavaScriptReplayWorker.js +95 -11
  201. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  202. package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
  203. package/dist/replay/ReplayOutcome.js +26 -15
  204. package/dist/replay/ReplayWorkerProtocol.js +34 -29
  205. package/dist/server/createServer.js +101 -144
  206. package/dist/server/mcpClientMetadata.js +32 -0
  207. package/dist/server/registerApplicationTools/characterization.js +6 -13
  208. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
  209. package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
  210. package/dist/server/registerApplicationTools/compareVersions.js +3 -8
  211. package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
  212. package/dist/server/registerApplicationTools/coverage.js +13 -19
  213. package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
  214. package/dist/server/registerApplicationTools/readiness.js +1 -6
  215. package/dist/server/registerApplicationTools/traceFeature.js +3 -8
  216. package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
  217. package/dist/server/registerArtifactComparisonTool.js +12 -16
  218. package/dist/server/registerBrowserScenarioTool.js +1 -6
  219. package/dist/server/registerBrowserTools.js +37 -79
  220. package/dist/server/registerBundleComparisonTool.js +10 -14
  221. package/dist/server/registerCloseLifecycleTool.js +6 -14
  222. package/dist/server/registerElectronTools.js +30 -47
  223. package/dist/server/registerEnhancedTools.js +124 -122
  224. package/dist/server/registerEvidenceResources.js +50 -101
  225. package/dist/server/registerEvidenceTools.js +5 -9
  226. package/dist/server/registerFunctionComparisonTool.js +11 -15
  227. package/dist/server/registerInvestigationTools.js +42 -59
  228. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
  229. package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
  230. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
  231. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  232. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
  233. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
  234. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
  235. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
  236. package/dist/server/registerOfficialTools.js +8 -9
  237. package/dist/server/registerProcessComparisonTool.js +19 -24
  238. package/dist/server/registerReconstructionObligationLedgerResource.js +0 -7
  239. package/dist/server/registerReconstructionReadinessResource.js +0 -7
  240. package/dist/server/registerReplayMachineTool.js +4 -10
  241. package/dist/server/registerSessionRecordTools.js +146 -47
  242. package/dist/server/registerSessionStatusTool.js +14 -29
  243. package/dist/server/registerSessionTools.js +45 -41
  244. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  245. package/dist/server/sessionToolPolicies.js +1 -5
  246. package/dist/server/toolRegistrationOptions.js +4 -177
  247. package/dist/server/toolResult.js +14 -18
  248. package/package.json +35 -16
  249. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  250. package/scripts/electron-active-hook.cjs +501 -0
  251. package/skills/reverse-engineer-anything/SKILL.md +10 -3
  252. package/dist/server/DynamicToolAvailability.js +0 -70
  253. package/dist/server/toolInputValidation.js +0 -77
@@ -0,0 +1,501 @@
1
+ "use strict";
2
+
3
+ const {
4
+ createElectronActiveBoundaryPatches,
5
+ } = require("./electron-active-hook-boundaries.cjs");
6
+
7
+ const boundedEnvironmentNumber = (name, fallback) => {
8
+ const value = Number(process.env[name]);
9
+ return Number.isInteger(value)
10
+ ? Math.min(20_000, Math.max(1, value))
11
+ : fallback;
12
+ };
13
+
14
+ const MAX_EVENT_NAME_LENGTH = 128;
15
+ const MAX_CHANNEL_LENGTH = 1_024;
16
+ const MAX_IDENTIFIER_LENGTH = 256;
17
+ const MAX_ARGUMENT_SHAPES = 32;
18
+ const maxEvents = boundedEnvironmentNumber(
19
+ "REA_ELECTRON_ACTIVE_MAX_RUNTIME_EVENTS",
20
+ 5_000,
21
+ );
22
+ const ipcEventKinds = new Set([
23
+ "main-handler-invocation",
24
+ "main-event-invocation",
25
+ "utility-process-fork",
26
+ "utility-process-message",
27
+ "ipc-main-to-renderer",
28
+ "ipc-utility-to-main",
29
+ "ipc-renderer-send",
30
+ "ipc-renderer-invoke",
31
+ "ipc-renderer-post-message",
32
+ ]);
33
+ const events = [];
34
+ let observed = 0;
35
+ let observedIpc = 0;
36
+ let observedRuntime = 0;
37
+ let truncated = false;
38
+ let sequence = 0;
39
+ let correlationSequence = 0;
40
+
41
+ const boundedString = (value, maximum) =>
42
+ typeof value === "string" ? value.slice(0, maximum) : null;
43
+
44
+ const shape = (value, depth = 0) => {
45
+ if (depth > 2 || value === null) return value === null ? "null" : "nested";
46
+ if (Array.isArray(value)) return "array";
47
+ switch (typeof value) {
48
+ case "string":
49
+ return "string";
50
+ case "number":
51
+ return "number";
52
+ case "boolean":
53
+ return "boolean";
54
+ case "undefined":
55
+ return "undefined";
56
+ case "function":
57
+ return "function";
58
+ case "object":
59
+ return "object";
60
+ default:
61
+ return "unknown";
62
+ }
63
+ };
64
+
65
+ const isAllowedNavigation = (value) => {
66
+ if (typeof value !== "string") return true;
67
+ try {
68
+ const parsed = new URL(value);
69
+ if (["file:", "data:", "about:"].includes(parsed.protocol)) return true;
70
+ return (
71
+ ["http:", "https:"].includes(parsed.protocol) &&
72
+ ["127.0.0.1", "localhost", "[::1]", "::1"].includes(parsed.hostname)
73
+ );
74
+ } catch {
75
+ return false;
76
+ }
77
+ };
78
+
79
+ const processType = () =>
80
+ typeof process.type === "string" && process.type.length > 0
81
+ ? process.type.slice(0, MAX_IDENTIFIER_LENGTH)
82
+ : "main";
83
+
84
+ const identity = (value, prefix) => {
85
+ if (value === null || value === undefined) return null;
86
+ const id = value.id;
87
+ const processId = value.pid;
88
+ return typeof id === "string" || typeof id === "number"
89
+ ? `${prefix}:${String(id)}`.slice(0, MAX_IDENTIFIER_LENGTH)
90
+ : typeof processId === "number"
91
+ ? `${prefix}:pid:${String(processId)}`.slice(0, MAX_IDENTIFIER_LENGTH)
92
+ : null;
93
+ };
94
+
95
+ const frameIdentity = (event) => {
96
+ const frame = event?.senderFrame ?? event?.frame;
97
+ const id = frame?.frameTreeNodeId ?? frame?.routingId ?? frame?.id;
98
+ return typeof id === "string" || typeof id === "number"
99
+ ? `frame:${String(id)}`.slice(0, MAX_IDENTIFIER_LENGTH)
100
+ : null;
101
+ };
102
+
103
+ const record = (event) => {
104
+ observed += 1;
105
+ if (ipcEventKinds.has(event.kind)) observedIpc += 1;
106
+ else observedRuntime += 1;
107
+ if (events.length >= maxEvents) {
108
+ truncated = true;
109
+ return null;
110
+ }
111
+ const raw = {
112
+ sequence: ++sequence,
113
+ correlation_id:
114
+ typeof event.correlation_id === "string"
115
+ ? event.correlation_id
116
+ : `capture:${process.pid}:${++correlationSequence}`,
117
+ event: null,
118
+ phase: "observed",
119
+ channel: null,
120
+ channel_truncated: false,
121
+ direction: null,
122
+ sender: null,
123
+ receiver: null,
124
+ frame: null,
125
+ target: null,
126
+ argument_shapes: [],
127
+ argument_shapes_truncated: false,
128
+ result_shape: null,
129
+ process_type: processType(),
130
+ source: "electron-active-hook",
131
+ capture_method: "api-wrapper",
132
+ artifact_path: null,
133
+ artifact_sha256: null,
134
+ error: false,
135
+ ...event,
136
+ };
137
+ const argumentShapes = Array.isArray(raw.argument_shapes)
138
+ ? raw.argument_shapes
139
+ : [];
140
+ events.push({
141
+ ...raw,
142
+ correlation_id: boundedString(raw.correlation_id, MAX_IDENTIFIER_LENGTH),
143
+ event: boundedString(raw.event, MAX_EVENT_NAME_LENGTH),
144
+ channel: boundedString(raw.channel, MAX_CHANNEL_LENGTH),
145
+ channel_truncated:
146
+ raw.channel_truncated === true ||
147
+ (typeof raw.channel === "string" &&
148
+ raw.channel.length > MAX_CHANNEL_LENGTH),
149
+ sender: boundedString(raw.sender, MAX_IDENTIFIER_LENGTH),
150
+ receiver: boundedString(raw.receiver, MAX_IDENTIFIER_LENGTH),
151
+ frame: boundedString(raw.frame, MAX_IDENTIFIER_LENGTH),
152
+ target: boundedString(raw.target, MAX_IDENTIFIER_LENGTH),
153
+ argument_shapes: argumentShapes
154
+ .slice(0, MAX_ARGUMENT_SHAPES)
155
+ .map((value) => boundedString(value, 64) ?? "unknown"),
156
+ argument_shapes_truncated:
157
+ raw.argument_shapes_truncated === true ||
158
+ argumentShapes.length > MAX_ARGUMENT_SHAPES,
159
+ result_shape: boundedString(raw.result_shape, 64),
160
+ process_type: boundedString(raw.process_type, MAX_IDENTIFIER_LENGTH),
161
+ artifact_path: boundedString(raw.artifact_path, 16_384),
162
+ artifact_sha256: boundedString(raw.artifact_sha256, 64),
163
+ });
164
+ return events.at(-1);
165
+ };
166
+
167
+ const recordRuntime = (kind, event, phase, details = {}) =>
168
+ record({ kind, event, phase, ...details });
169
+
170
+ const recordIpc = (kind, channel, args, details = {}) =>
171
+ (() => {
172
+ const values = Array.isArray(args) ? args : [];
173
+ return record({
174
+ kind,
175
+ channel: typeof channel === "string" ? channel : null,
176
+ argument_shapes: values
177
+ .slice(0, MAX_ARGUMENT_SHAPES)
178
+ .map((value) => shape(value)),
179
+ argument_shapes_truncated: values.length > MAX_ARGUMENT_SHAPES,
180
+ ...details,
181
+ });
182
+ })();
183
+
184
+ const patchEmitter = (emitter, observeEvent) => {
185
+ if (emitter === null || emitter === undefined) return;
186
+ const original = emitter.emit;
187
+ if (typeof original !== "function") return;
188
+ if (emitter.__reaElectronActiveEmitPatched === true) return;
189
+ try {
190
+ emitter.__reaElectronActiveEmitPatched = true;
191
+ emitter.emit = function patchedEmit(event, ...args) {
192
+ if (typeof event === "string") observeEvent.call(this, event, args);
193
+ return original.call(this, event, ...args);
194
+ };
195
+ } catch {
196
+ globalThis.__reaElectronActiveHookError = true;
197
+ }
198
+ };
199
+
200
+ const recordInvocation = (kind, channel, event, args) =>
201
+ recordIpc(kind, channel, args, {
202
+ direction: "renderer-to-main",
203
+ sender: identity(event?.sender, "webContents"),
204
+ receiver: "main",
205
+ frame: frameIdentity(event),
206
+ process_type: "main",
207
+ error: false,
208
+ });
209
+
210
+ const patchIpcMain = (ipcMain) => {
211
+ if (ipcMain === null || ipcMain === undefined) return;
212
+ for (const [method, kind] of [
213
+ ["handle", "main-handler-invocation"],
214
+ ["on", "main-event-invocation"],
215
+ ["once", "main-event-invocation"],
216
+ ]) {
217
+ const original = ipcMain[method];
218
+ if (typeof original !== "function") continue;
219
+ ipcMain[method] = function patchedIpcMain(channel, listener) {
220
+ if (typeof listener !== "function")
221
+ return original.call(this, channel, listener);
222
+ const wrapped =
223
+ kind === "main-handler-invocation"
224
+ ? async function wrappedHandler(event, ...args) {
225
+ const recorded = recordInvocation(kind, channel, event, args);
226
+ try {
227
+ const result = await listener.call(this, event, ...args);
228
+ if (recorded !== null) recorded.result_shape = shape(result);
229
+ return result;
230
+ } catch (cause) {
231
+ if (recorded !== null) recorded.error = true;
232
+ throw cause;
233
+ }
234
+ }
235
+ : function wrappedEventListener(event, ...args) {
236
+ const recorded = recordInvocation(kind, channel, event, args);
237
+ try {
238
+ return listener.call(this, event, ...args);
239
+ } catch (cause) {
240
+ if (recorded !== null) recorded.error = true;
241
+ throw cause;
242
+ }
243
+ };
244
+ return original.call(this, channel, wrapped);
245
+ };
246
+ }
247
+ };
248
+
249
+ const patchNavigationMethods = (webContents, contentsId) => {
250
+ for (const method of ["loadURL", "loadFile", "loadDataURL"]) {
251
+ const original = webContents[method];
252
+ if (typeof original !== "function") continue;
253
+ webContents[method] = function patchedNavigation(...args) {
254
+ recordRuntime("navigation", method, "attempted", {
255
+ target: contentsId,
256
+ argument_shapes: args.map((value) => shape(value)),
257
+ });
258
+ if (method === "loadURL" && !isAllowedNavigation(args[0])) {
259
+ recordRuntime("navigation", method, "blocked", {
260
+ target: contentsId,
261
+ error: true,
262
+ });
263
+ return Promise.reject(new Error("External navigation is blocked"));
264
+ }
265
+ try {
266
+ const result = original.apply(this, args);
267
+ if (result !== null && typeof result?.then === "function")
268
+ return result.then(
269
+ (value) => {
270
+ recordRuntime("navigation", method, "completed", {
271
+ target: contentsId,
272
+ });
273
+ return value;
274
+ },
275
+ (cause) => {
276
+ recordRuntime("navigation", method, "failed", {
277
+ target: contentsId,
278
+ error: true,
279
+ });
280
+ throw cause;
281
+ },
282
+ );
283
+ recordRuntime("navigation", method, "completed", {
284
+ target: contentsId,
285
+ });
286
+ return result;
287
+ } catch (cause) {
288
+ recordRuntime("navigation", method, "failed", {
289
+ target: contentsId,
290
+ error: true,
291
+ });
292
+ throw cause;
293
+ }
294
+ };
295
+ }
296
+ };
297
+
298
+ const patchWebContentsIpc = (webContents, contentsId) => {
299
+ const originalSend = webContents.send;
300
+ if (typeof originalSend === "function")
301
+ webContents.send = function patchedSend(channel, ...args) {
302
+ const recorded = recordIpc("ipc-main-to-renderer", channel, args, {
303
+ direction: "main-to-renderer",
304
+ sender: "main",
305
+ receiver: contentsId,
306
+ target: contentsId,
307
+ process_type: "main",
308
+ error: false,
309
+ });
310
+ try {
311
+ const result = originalSend.call(this, channel, ...args);
312
+ if (recorded !== null) recorded.result_shape = shape(result);
313
+ return result;
314
+ } catch (cause) {
315
+ if (recorded !== null) recorded.error = true;
316
+ throw cause;
317
+ }
318
+ };
319
+ const originalPostMessage = webContents.postMessage;
320
+ if (typeof originalPostMessage === "function")
321
+ webContents.postMessage = function patchedPostMessage(
322
+ channel,
323
+ message,
324
+ transfer,
325
+ ) {
326
+ const recorded = recordIpc(
327
+ "ipc-main-to-renderer",
328
+ channel,
329
+ [message, transfer],
330
+ {
331
+ direction: "main-to-renderer",
332
+ sender: "main",
333
+ receiver: contentsId,
334
+ target: contentsId,
335
+ process_type: "main",
336
+ error: false,
337
+ },
338
+ );
339
+ try {
340
+ const result = originalPostMessage.call(
341
+ this,
342
+ channel,
343
+ message,
344
+ transfer,
345
+ );
346
+ if (recorded !== null) recorded.result_shape = shape(result);
347
+ return result;
348
+ } catch (cause) {
349
+ if (recorded !== null) recorded.error = true;
350
+ throw cause;
351
+ }
352
+ };
353
+ };
354
+
355
+ const patchWebContents = (webContents, windowId) => {
356
+ if (webContents === null || webContents === undefined) return;
357
+ const contentsId = identity(webContents, "webContents");
358
+ patchEmitter(webContents, (event, args) => {
359
+ const navigation = [
360
+ "did-start-loading",
361
+ "did-stop-loading",
362
+ "did-finish-load",
363
+ "did-fail-load",
364
+ "did-frame-finish-load",
365
+ "will-navigate",
366
+ "will-redirect",
367
+ ].includes(event);
368
+ const kind = navigation
369
+ ? "navigation"
370
+ : [
371
+ "console-message",
372
+ "render-process-gone",
373
+ "crashed",
374
+ "unresponsive",
375
+ "responsive",
376
+ ].includes(event)
377
+ ? "error"
378
+ : event === "did-create-window"
379
+ ? "popup-attempt"
380
+ : "web-contents-lifecycle";
381
+ if (event === "will-navigate" || event === "will-redirect") {
382
+ if (!isAllowedNavigation(args[1])) {
383
+ const preventDefault = args[0]?.preventDefault;
384
+ if (typeof preventDefault === "function") preventDefault.call(args[0]);
385
+ recordRuntime("navigation", event, "blocked", {
386
+ target: contentsId,
387
+ sender: windowId,
388
+ argument_shapes: args.map((value) => shape(value)),
389
+ error: true,
390
+ });
391
+ return;
392
+ }
393
+ }
394
+ recordRuntime(kind, event, "observed", {
395
+ target: contentsId,
396
+ sender: windowId,
397
+ argument_shapes: args.map((value) => shape(value)),
398
+ error: kind === "error",
399
+ });
400
+ if (event === "did-create-window") {
401
+ const childWindow = args[0];
402
+ patchWebContents(
403
+ childWindow?.webContents,
404
+ identity(childWindow, "window"),
405
+ );
406
+ }
407
+ });
408
+ patchNavigationMethods(webContents, contentsId);
409
+ patchWebContentsIpc(webContents, contentsId);
410
+ boundaries.patchWindowOpenHandler(webContents, contentsId);
411
+ };
412
+
413
+ const patchBrowserWindow = (electron) => {
414
+ const original = electron.BrowserWindow;
415
+ if (typeof original !== "function") return;
416
+ electron.BrowserWindow = new Proxy(original, {
417
+ construct(target, args, newTarget) {
418
+ const window = Reflect.construct(target, args, newTarget);
419
+ const targetId = identity(window, "window");
420
+ recordRuntime("window-lifecycle", "created", "completed", {
421
+ target: targetId,
422
+ argument_shapes: args.map((value) => shape(value)),
423
+ });
424
+ const preload = args[0]?.webPreferences?.preload;
425
+ if (typeof preload === "string")
426
+ recordRuntime("preload", "configured", "completed", {
427
+ target: targetId,
428
+ artifact_path: preload,
429
+ });
430
+ patchEmitter(window, (event) =>
431
+ recordRuntime("window-lifecycle", event, "observed", {
432
+ target: targetId,
433
+ }),
434
+ );
435
+ patchWebContents(window.webContents, targetId);
436
+ return window;
437
+ },
438
+ });
439
+ };
440
+
441
+ const boundaries = createElectronActiveBoundaryPatches({
442
+ identity,
443
+ patchEmitter,
444
+ processType,
445
+ recordIpc,
446
+ recordRuntime,
447
+ shape,
448
+ });
449
+
450
+ try {
451
+ const electron = require("electron");
452
+ patchEmitter(electron.app, (event, args) =>
453
+ recordRuntime(
454
+ event === "open-url" || event === "second-instance"
455
+ ? "protocol"
456
+ : "app-lifecycle",
457
+ event,
458
+ "observed",
459
+ {
460
+ target: "app",
461
+ argument_shapes: args.map((value) => shape(value)),
462
+ process_type: "main",
463
+ },
464
+ ),
465
+ );
466
+ patchIpcMain(electron.ipcMain);
467
+ boundaries.patchIpcRenderer(electron.ipcRenderer);
468
+ boundaries.patchContextBridge(electron.contextBridge);
469
+ patchBrowserWindow(electron);
470
+ boundaries.patchUtilityProcess(electron.utilityProcess);
471
+ boundaries.patchShell(electron.shell);
472
+ boundaries.patchSessionManager(electron.session);
473
+ boundaries.patchApplicationEffects(electron.app);
474
+ boundaries.patchNativeAddonLoading();
475
+ boundaries.patchChildProcess();
476
+ process.once("uncaughtException", (cause, origin) => {
477
+ recordRuntime("process-lifecycle", "uncaught-exception", "observed", {
478
+ argument_shapes: [shape(cause), shape(origin)],
479
+ error: true,
480
+ });
481
+ throw cause;
482
+ });
483
+ process.once("unhandledRejection", (reason, promise) => {
484
+ recordRuntime("process-lifecycle", "unhandled-rejection", "observed", {
485
+ argument_shapes: [shape(reason), shape(promise)],
486
+ error: true,
487
+ });
488
+ throw reason;
489
+ });
490
+ } catch {
491
+ globalThis.__reaElectronActiveHookError = true;
492
+ }
493
+
494
+ globalThis.__reaElectronActiveSnapshot = () => ({
495
+ events: events.slice(),
496
+ observed,
497
+ observed_ipc: observedIpc,
498
+ observed_runtime: observedRuntime,
499
+ truncated,
500
+ hook_error: globalThis.__reaElectronActiveHookError === true,
501
+ });
@@ -3,8 +3,8 @@ name: reverse-engineer-anything
3
3
  description: Reverse engineer native, managed, Electron/JavaScript, packaged, and browser applications with REA. Use shipped-artifact or approved runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
4
4
  metadata:
5
5
  version: "23"
6
- tool_count: 110
7
- catalog_digest: "e8cac51f2f17a5b9a088c3ff773473c4897823401481fc0875a28fe7daf8eee0"
6
+ tool_count: 116
7
+ catalog_digest: "bab5657d9525ec4f798d0a9ef6001412d9c11f77fb0ddc925c7076fd10921dc9"
8
8
  ---
9
9
 
10
10
  # REA
@@ -23,7 +23,8 @@ Choose the first tool from the target the user supplied. Do not call
23
23
  - ASAR or extracted JavaScript/Electron tree:
24
24
  `analyze_javascript_application`.
25
25
  - Archive, application package, ZIP/APK/IPA/MSIX/AppX, or DMG:
26
- `inventory_artifact`.
26
+ `open_binary` with the supplied local path, then `inspect_artifact` or
27
+ `inventory_artifact` (both operate on the active target and accept no path).
27
28
  - Managed PE/CLI assembly: `inspect_managed_artifact`.
28
29
  - User-owned browser page already open: `list_browser_targets`.
29
30
  - User-owned Electron runtime already open: `list_electron_targets`.
@@ -34,6 +35,12 @@ If the app is missing, ask which app to inspect. Resolve a human-readable app
34
35
  name to one clear installed artifact when possible; ask only when matches are
35
36
  ambiguous. Never choose an example app on the user's behalf.
36
37
 
38
+ In a target-free session, use `open_binary` to bind any archive/package or
39
+ native target whose analysis tool operates on the active target. Do not call a
40
+ tool hidden from `tools/list`; inspect `binary_session` with
41
+ `detail: "capabilities"` for the exact remediation when a desired capability
42
+ is unavailable.
43
+
37
44
  ## Work summary-first
38
45
 
39
46
  Start with the default summary projection. Do not repeat an identical tool call.
@@ -1,70 +0,0 @@
1
- import { buildCapabilityInventory, } from "../application/CapabilityInventory.js";
2
- /**
3
- * Track public SDK tool handles and keep their visible state synchronized with
4
- * the same availability projection returned by `binary_session`.
5
- */
6
- export const installDynamicToolAvailability = (server, session, policy) => {
7
- const tools = new Map();
8
- const originalRegisterTool = server.registerTool.bind(server);
9
- const originalSendToolListChanged = server.sendToolListChanged.bind(server);
10
- let synchronizing = false;
11
- const controller = {
12
- synchronize: () => {
13
- if (synchronizing)
14
- return false;
15
- synchronizing = true;
16
- try {
17
- const availability = new Map(buildCapabilityInventory(session.status(), policy(), clientFeatures(server)).map((item) => [item.name, item.available]));
18
- let changed = false;
19
- for (const [name, tool] of tools) {
20
- const enabled = availability.get(name) === true;
21
- if (tool.enabled === enabled)
22
- continue;
23
- changed = true;
24
- if (enabled)
25
- tool.enable();
26
- else
27
- tool.disable();
28
- }
29
- return changed;
30
- }
31
- finally {
32
- synchronizing = false;
33
- }
34
- },
35
- };
36
- const wrappedRegisterTool = (...args) => {
37
- const name = args[0];
38
- if (typeof name !== "string")
39
- throw new TypeError("MCP tool registration requires a string name");
40
- const registered = Reflect.apply(originalRegisterTool, server, args);
41
- if (!isRegisteredTool(registered))
42
- throw new TypeError(`MCP SDK did not return a tool handle for ${name}`);
43
- tools.set(name, registered);
44
- return registered;
45
- };
46
- if (!Reflect.set(server, "registerTool", wrappedRegisterTool))
47
- throw new TypeError("Unable to install dynamic MCP tool registration");
48
- if (!Reflect.set(server, "sendToolListChanged", () => {
49
- if (controller.synchronize())
50
- originalSendToolListChanged();
51
- }))
52
- throw new TypeError("Unable to install dynamic MCP tool notifications");
53
- return controller;
54
- };
55
- const clientFeatures = (server) => {
56
- const capabilities = server.server.getClientCapabilities();
57
- return {
58
- elicitation_form: capabilities?.elicitation?.form !== undefined,
59
- elicitation_url: capabilities?.elicitation?.url !== undefined,
60
- roots: capabilities?.roots !== undefined,
61
- sampling: capabilities?.sampling !== undefined,
62
- };
63
- };
64
- const isRegisteredTool = (value) => {
65
- if (typeof value !== "object" || value === null)
66
- return false;
67
- return (typeof Reflect.get(value, "enabled") === "boolean" &&
68
- typeof Reflect.get(value, "enable") === "function" &&
69
- typeof Reflect.get(value, "disable") === "function");
70
- };
@@ -1,77 +0,0 @@
1
- import { z } from "zod";
2
- import { AnalysisInputError, } from "../domain/errors.js";
3
- import { projectInputIssues } from "../domain/inputIssueProjection.js";
4
- import { err, ok } from "../domain/result.js";
5
- import { closeObjectSchemas } from "./toolRegistrationOptions.js";
6
- /** Parse one MCP request exactly once and retain only schema-owned correction data. */
7
- export const safeParseToolInput = (schema, input, operation) => {
8
- const unknownIssues = unknownArgumentIssues(schema, input);
9
- if (unknownIssues.length > 0)
10
- return err(new AnalysisInputError(operation, undefined, unknownIssues));
11
- const parsed = schema.safeParse(input);
12
- return parsed.success
13
- ? ok(parsed.data)
14
- : err(new AnalysisInputError(operation, undefined, projectInputIssues(parsed.error.issues, input)));
15
- };
16
- const schemaCache = new WeakMap();
17
- const unknownArgumentIssues = (schema, input) => {
18
- let jsonSchema = schemaCache.get(schema);
19
- if (jsonSchema === undefined) {
20
- const converter = schema["~standard"].jsonSchema?.input;
21
- if (converter === undefined)
22
- throw new TypeError("Tool input schema does not expose Standard JSON Schema");
23
- jsonSchema = closeObjectSchemas(converter({ target: "draft-2020-12" }));
24
- schemaCache.set(schema, jsonSchema);
25
- }
26
- return scanUnknownArguments(input, jsonSchema, jsonSchema, []);
27
- };
28
- const scanUnknownArguments = (value, schema, root, path) => {
29
- const resolved = resolveSchema(schema, root);
30
- if (Array.isArray(value)) {
31
- const items = objectValue(resolved.items);
32
- return items === undefined
33
- ? []
34
- : value.flatMap((item, index) => scanUnknownArguments(item, items, root, [...path, index]));
35
- }
36
- if (!isObject(value))
37
- return [];
38
- const variants = schemaVariants(resolved, root);
39
- const properties = Object.fromEntries(variants.flatMap((variant) => Object.entries(objectValue(variant.properties) ?? {})));
40
- const closed = variants.length > 0 &&
41
- variants.every((variant) => variant.additionalProperties !== true &&
42
- !isObject(variant.additionalProperties));
43
- const issues = [];
44
- for (const [key, child] of Object.entries(value)) {
45
- const propertySchema = objectValue(properties[key]);
46
- if (propertySchema === undefined) {
47
- if (closed)
48
- issues.push({ path: [...path, key], reason: "unknown_argument" });
49
- continue;
50
- }
51
- issues.push(...scanUnknownArguments(child, propertySchema, root, [...path, key]));
52
- }
53
- return issues;
54
- };
55
- const schemaVariants = (schema, root) => {
56
- const resolved = resolveSchema(schema, root);
57
- const variants = [resolved.oneOf, resolved.anyOf, resolved.allOf]
58
- .flatMap((value) => (Array.isArray(value) ? value : []))
59
- .flatMap((value) => {
60
- const object = objectValue(value);
61
- return object === undefined ? [] : schemaVariants(object, root);
62
- });
63
- if (variants.length > 0)
64
- return variants;
65
- return resolved.type === "object" || isObject(resolved.properties)
66
- ? [resolved]
67
- : [];
68
- };
69
- const resolveSchema = (schema, root) => {
70
- const reference = schema.$ref;
71
- if (typeof reference !== "string" || !reference.startsWith("#/$defs/"))
72
- return schema;
73
- const definition = objectValue(objectValue(root.$defs)?.[reference.slice(8)]);
74
- return definition === undefined ? schema : definition;
75
- };
76
- const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
77
- const objectValue = (value) => isObject(value) ? value : undefined;