rea-agents 3.0.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 (219) hide show
  1. package/README.md +14 -16
  2. package/dist/application/AnalysisContextQueries.js +21 -9
  3. package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
  4. package/dist/application/ArtifactInventory/policy.js +17 -0
  5. package/dist/application/ArtifactInventory/reader.js +1 -4
  6. package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
  7. package/dist/application/ArtifactInventory/scanReader.js +7 -7
  8. package/dist/application/ArtifactInventory/types.js +1 -5
  9. package/dist/application/BinarySession.js +14 -16
  10. package/dist/application/BinarySessionRecords.js +31 -5
  11. package/dist/application/BinarySessionStatus.js +11 -5
  12. package/dist/application/BrowserEvidence.js +3 -5
  13. package/dist/application/CapabilityClientRequirements.js +26 -0
  14. package/dist/application/CapabilityInventory.js +134 -63
  15. package/dist/application/CrossVersionInventory.js +7 -6
  16. package/dist/application/ElectronActiveEvidence.js +55 -0
  17. package/dist/application/ElectronActiveObservationPort.js +1 -0
  18. package/dist/application/ElectronActiveObservationService.js +81 -0
  19. package/dist/application/EnhancedTools.js +22 -20
  20. package/dist/application/EvidenceBundleCommands.js +5 -1
  21. package/dist/application/EvidenceLedger.js +8 -1
  22. package/dist/application/JavaScriptReplayPermission.js +1 -1
  23. package/dist/application/JavaScriptReplayService.js +23 -15
  24. package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
  25. package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
  26. package/dist/application/ProcessCaptureLifecycle.js +5 -0
  27. package/dist/application/ProcessCli.js +2 -1
  28. package/dist/application/ProcessHarness.js +8 -3
  29. package/dist/application/ProcessNormalization.js +2 -1
  30. package/dist/application/ProjectPermissionStore.js +1 -0
  31. package/dist/application/ReferenceSourceImport.js +2 -2
  32. package/dist/application/SetupClientConfiguration.js +6 -1
  33. package/dist/application/WindowsCapabilities.js +5 -4
  34. package/dist/artifacts/ArtifactProvider.js +8 -10
  35. package/dist/artifacts/SafeOutputTree.js +7 -8
  36. package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
  37. package/dist/browser/CdpElectronInspection.js +3 -1
  38. package/dist/browser/JavaScriptRuntimeScope.js +5 -0
  39. package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
  40. package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
  41. package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
  42. package/dist/browser/PlaywrightScenarioSession.js +4 -4
  43. package/dist/browser/SensitiveTextCapture.js +1 -1
  44. package/dist/browser/V8InspectorCaptureProjection.js +1 -0
  45. package/dist/browser/V8InspectorProvider.js +3 -3
  46. package/dist/catalogIdentity.js +12 -6
  47. package/dist/cli/managedCommands.js +1 -1
  48. package/dist/cliApplicationCommands.js +2 -2
  49. package/dist/cliBrowserAdvancedCommands.js +11 -5
  50. package/dist/cliBrowserCommands.js +14 -7
  51. package/dist/cliCommandNames.js +1 -0
  52. package/dist/cliElectronCommands.js +46 -4
  53. package/dist/cliJavaScriptRuntimeCommands.js +14 -6
  54. package/dist/cliObservationOptions.js +4 -0
  55. package/dist/cliPolicyCommands.js +1 -0
  56. package/dist/config/browserScenario.js +77 -0
  57. package/dist/config/electronAutomation.js +35 -0
  58. package/dist/config/environment.js +6 -0
  59. package/dist/config/javascriptReplay.js +41 -0
  60. package/dist/config/managedRuntime.js +25 -0
  61. package/dist/config/parseConfig.js +56 -200
  62. package/dist/config/parsers.js +10 -1
  63. package/dist/config/passiveObservation.js +157 -0
  64. package/dist/config/processCapture.js +47 -0
  65. package/dist/contracts/applicationToolContracts.js +2 -5
  66. package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
  67. package/dist/contracts/artifactToolContracts.js +27 -34
  68. package/dist/contracts/browserToolContracts.js +2 -2
  69. package/dist/contracts/electronToolContracts.js +30 -1
  70. package/dist/contracts/enhancedInputs.js +13 -29
  71. package/dist/contracts/functionWorkflowToolContracts.js +2 -3
  72. package/dist/contracts/managedToolContracts.js +4 -9
  73. package/dist/contracts/managedWorkflowExamples.js +12 -9
  74. package/dist/contracts/managedWorkflowToolContracts.js +30 -27
  75. package/dist/contracts/nativeToolContracts.js +2 -3
  76. package/dist/contracts/sessionToolSchemas.js +61 -0
  77. package/dist/contracts/toolContractExamples.js +1 -0
  78. package/dist/contracts/toolContractHelpers.js +23 -0
  79. package/dist/contracts/toolContracts.js +5 -77
  80. package/dist/contracts/toolEffects.js +15 -0
  81. package/dist/contracts/toolOutputSchemaGroups.js +17 -2
  82. package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
  83. package/dist/contracts/toolSchemaMetadata.js +128 -0
  84. package/dist/doctorRuntime.js +1 -1
  85. package/dist/domain/androidApplication.js +2 -0
  86. package/dist/domain/appleApplication.js +2 -0
  87. package/dist/domain/binaryTarget.js +7 -5
  88. package/dist/domain/binaryTargetTypes.js +1 -0
  89. package/dist/domain/browserCaptureComparison.js +21 -69
  90. package/dist/domain/browserObservation.js +22 -9
  91. package/dist/domain/bytecodeProvider.js +33 -35
  92. package/dist/domain/callPath.js +3 -2
  93. package/dist/domain/conformanceReplay.js +3 -3
  94. package/dist/domain/conformanceTrustGate.js +151 -16
  95. package/dist/domain/customProtocolCapture.js +3 -3
  96. package/dist/domain/electronActiveObservation.js +277 -0
  97. package/dist/domain/electronObservation.js +15 -11
  98. package/dist/domain/electronStaticAnalysisValues.js +4 -1
  99. package/dist/domain/eventProcessTree.js +82 -79
  100. package/dist/domain/functionComparisonNormalization.js +15 -8
  101. package/dist/domain/functionDossierEvidence.js +9 -4
  102. package/dist/domain/hopperValues.js +68 -71
  103. package/dist/domain/inputIssueProjection.js +4 -1
  104. package/dist/domain/investigationWorkspace.js +16 -15
  105. package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
  106. package/dist/domain/javascriptReplay.js +79 -63
  107. package/dist/domain/javascriptRuntimeObservation.js +1 -0
  108. package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
  109. package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
  110. package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
  111. package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
  112. package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
  113. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  114. package/dist/domain/knownPageCoverage.js +15 -7
  115. package/dist/domain/nativeApiBoundary.js +15 -7
  116. package/dist/domain/nodeRuntimeCharacterization.js +14 -13
  117. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  118. package/dist/domain/processCaptureValidation.js +7 -3
  119. package/dist/domain/processComparison.js +12 -7
  120. package/dist/domain/processObservation.js +5 -6
  121. package/dist/domain/processReactiveMatching.js +14 -7
  122. package/dist/domain/processReactiveTransition.js +9 -3
  123. package/dist/domain/processScenario.js +6 -3
  124. package/dist/domain/processTraceComparison.js +3 -2
  125. package/dist/domain/protocolCapture.js +8 -6
  126. package/dist/domain/reconstructionReadinessSchemas.js +30 -2
  127. package/dist/domain/referenceSourceImportParsing.js +2 -2
  128. package/dist/domain/replayMachineRuntime.js +5 -3
  129. package/dist/domain/sourceToBundleComparison.js +2 -2
  130. package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
  131. package/dist/domain/sourceToBundleSignals.js +7 -1
  132. package/dist/domain/staticRuntimeCorrelation.js +7 -5
  133. package/dist/domain/webBundleAnalysis.js +14 -14
  134. package/dist/domain/webCaptureDiff.js +15 -12
  135. package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
  136. package/dist/generatedMcpToolCatalog.js +1 -1
  137. package/dist/generatedPackageMetadata.js +1 -1
  138. package/dist/ghidra/GhidraClient.js +1 -1
  139. package/dist/ghidra/GhidraClientStartup.js +1 -1
  140. package/dist/ghidra/GhidraFunctionValues.js +17 -15
  141. package/dist/ghidra/GhidraInventoryValues.js +57 -47
  142. package/dist/ghidra/GhidraProvider.js +18 -10
  143. package/dist/ghidra/GhidraProviderCapabilities.js +5 -1
  144. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  145. package/dist/ghidra/protocol.js +19 -42
  146. package/dist/hopper/BridgeLauncher.js +3 -1
  147. package/dist/hopper/HopperAnalysisProfile.js +2 -4
  148. package/dist/hopper/HopperCleanup.js +5 -6
  149. package/dist/hopper/HopperClient.js +1 -1
  150. package/dist/hopper/HopperProvider.js +0 -14
  151. package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
  152. package/dist/main/reload.js +1 -6
  153. package/dist/main/state.js +0 -14
  154. package/dist/main/transport.js +30 -37
  155. package/dist/main.js +17 -15
  156. package/dist/mcpDoctor.js +2 -24
  157. package/dist/process/PrivateRuntimeRoot.js +17 -0
  158. package/dist/process/ProcessOwnership.js +64 -128
  159. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  160. package/dist/process/ProcessOwnershipObservation.js +88 -0
  161. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  162. package/dist/process/ProviderDeadline.js +8 -12
  163. package/dist/process/WindowsAuthority.js +32 -0
  164. package/dist/reference/ReferenceSourceReader.js +3 -3
  165. package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
  166. package/dist/replay/JavaScriptReplayWorker.js +95 -11
  167. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  168. package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
  169. package/dist/replay/ReplayOutcome.js +26 -15
  170. package/dist/replay/ReplayWorkerProtocol.js +34 -29
  171. package/dist/server/createServer.js +158 -94
  172. package/dist/server/mcpClientMetadata.js +32 -0
  173. package/dist/server/registerApplicationTools/characterization.js +6 -13
  174. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
  175. package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
  176. package/dist/server/registerApplicationTools/compareVersions.js +3 -8
  177. package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
  178. package/dist/server/registerApplicationTools/coverage.js +13 -19
  179. package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
  180. package/dist/server/registerApplicationTools/readiness.js +1 -6
  181. package/dist/server/registerApplicationTools/traceFeature.js +3 -8
  182. package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
  183. package/dist/server/registerArtifactComparisonTool.js +12 -16
  184. package/dist/server/registerBrowserScenarioTool.js +1 -6
  185. package/dist/server/registerBrowserTools.js +37 -79
  186. package/dist/server/registerBundleComparisonTool.js +10 -14
  187. package/dist/server/registerCloseLifecycleTool.js +6 -14
  188. package/dist/server/registerElectronTools.js +30 -47
  189. package/dist/server/registerEnhancedTools.js +114 -122
  190. package/dist/server/registerEvidenceTools.js +5 -9
  191. package/dist/server/registerFunctionComparisonTool.js +11 -15
  192. package/dist/server/registerInvestigationTools.js +41 -57
  193. package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
  194. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
  195. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  196. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
  197. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
  198. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
  199. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
  200. package/dist/server/registerOfficialTools.js +8 -9
  201. package/dist/server/registerProcessComparisonTool.js +19 -24
  202. package/dist/server/registerReplayMachineTool.js +4 -10
  203. package/dist/server/registerSessionRecordTools.js +69 -40
  204. package/dist/server/registerSessionStatusTool.js +13 -28
  205. package/dist/server/registerSessionTools.js +36 -52
  206. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  207. package/dist/server/sessionToolPolicies.js +1 -5
  208. package/dist/server/toolRegistrationOptions.js +4 -192
  209. package/dist/server/toolResult.js +2 -18
  210. package/package.json +22 -14
  211. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  212. package/scripts/electron-active-hook.cjs +501 -0
  213. package/scripts/rea.mjs +1 -11
  214. package/skills/reverse-engineer-anything/SKILL.md +2 -2
  215. package/dist/server/DynamicToolAvailability.js +0 -70
  216. package/dist/server/LazyToolCatalog.js +0 -134
  217. package/dist/server/hydrateServerTools.js +0 -191
  218. package/dist/server/toolInputValidation.js +0 -77
  219. package/scripts/package-runner-bootstrap.mjs +0 -72
@@ -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
+ });
package/scripts/rea.mjs CHANGED
@@ -4,8 +4,6 @@ import { access } from "node:fs/promises";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
- import { runPackageRunnerSetupBootstrap } from "./package-runner-bootstrap.mjs";
8
-
9
7
  // Route production MCP before importing Incur. Incur owns registration helpers
10
8
  // such as `mcp add`, while only dist/main.js may serve the stdio tool catalog.
11
9
  const args = process.argv.slice(2);
@@ -17,21 +15,13 @@ const isMcpMode =
17
15
  args.length === 1 && (args[0] === "--mcp" || args[0] === "mcp");
18
16
  const isMcpDoctorMode = args[0] === "mcp" && args[1] === "doctor";
19
17
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
20
- const bootstrapExitCode = await runPackageRunnerSetupBootstrap({
21
- args,
22
- environment: process.env,
23
- packageRoot,
24
- packageName: packageJson.name,
25
- });
26
18
  const runtimeFiles = isMcpMode
27
19
  ? ["dist/main.js"]
28
20
  : isMcpDoctorMode
29
21
  ? ["dist/main.js", "dist/mcpDoctor.js"]
30
22
  : ["dist/cli.js", "dist/cliOutput.js"];
31
23
 
32
- if (bootstrapExitCode !== undefined) {
33
- process.exitCode = bootstrapExitCode;
34
- } else if (!(await compiledRuntimeExists(runtimeFiles))) {
24
+ if (!(await compiledRuntimeExists(runtimeFiles))) {
35
25
  process.stderr.write(
36
26
  `REA's compiled runtime is missing. Run \`npm ci\` in ${packageRoot} to install dependencies and build REA, then restart it. If this is an installed package, reinstall rea-agents.\n`,
37
27
  );
@@ -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: 114
7
- catalog_digest: "e83a177f5eca63bbad17886a61f5a1a376d44afe862c51c56e5d38339f7d41f8"
6
+ tool_count: 116
7
+ catalog_digest: "bab5657d9525ec4f798d0a9ef6001412d9c11f77fb0ddc925c7076fd10921dc9"
8
8
  ---
9
9
 
10
10
  # REA
@@ -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
- };