rea-agents 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +23 -17
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +173 -47
  4. package/bridge/hopper_bridge.py +310 -128
  5. package/bridge/mitmproxy/capture.py +0 -2
  6. package/bridge/native/rea_lldb_tracer.py +630 -94
  7. package/bridge/process/ProcessRunTokenReader.swift +39 -5
  8. package/bridge/pwntools/recorded_crash_impl.py +4 -0
  9. package/dist/android/JadxConfiguration.js +196 -33
  10. package/dist/android/JadxMcpTransport.js +4 -0
  11. package/dist/android/JadxProtocol.js +6 -0
  12. package/dist/android/JadxProvider.js +19 -2
  13. package/dist/android/JadxSession.js +23 -4
  14. package/dist/application/AnalysisContextQueries.js +8 -35
  15. package/dist/application/AnalysisDocument.js +32 -0
  16. package/dist/application/AppBundleExecutable.js +67 -21
  17. package/dist/application/CallPathTracing.js +19 -3
  18. package/dist/application/CapabilityInventory.js +6 -3
  19. package/dist/application/ClientConfigurationDocument.js +871 -6
  20. package/dist/application/ClientRegistrationIdentity.js +26 -5
  21. package/dist/application/ClientRegistrationStatus.js +29 -14
  22. package/dist/application/DirectAnalysis.js +27 -37
  23. package/dist/application/Doctor.js +4 -2
  24. package/dist/application/DoctorScope.js +25 -13
  25. package/dist/application/EnhancedLiteralTracing.js +22 -25
  26. package/dist/application/EnhancedTools.js +13 -11
  27. package/dist/application/EvidenceBundleFiles.js +23 -11
  28. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  29. package/dist/application/InventoryProjectionEvidence.js +4 -3
  30. package/dist/application/InvestigationProviders.js +3 -2
  31. package/dist/application/JsonFiles.js +50 -28
  32. package/dist/application/ProcedureAddressResolution.js +11 -0
  33. package/dist/application/ReconstructionCoverageService.js +7 -4
  34. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  35. package/dist/application/Setup.js +13 -1
  36. package/dist/application/SetupClientConfiguration.js +10 -15
  37. package/dist/application/SetupHost.js +5 -2
  38. package/dist/application/SetupPlan.js +5 -3
  39. package/dist/application/SupportedClients.js +34 -1
  40. package/dist/application/Uninstall.js +4 -3
  41. package/dist/application/Update.js +18 -3
  42. package/dist/application/UpdateRuntime.js +46 -25
  43. package/dist/application/WebModuleTraceService.js +4 -2
  44. package/dist/application/WebNetworkCaptureService.js +4 -2
  45. package/dist/application/WebRuntimeService.js +5 -3
  46. package/dist/application/WebScriptExportService.js +2 -2
  47. package/dist/application/WebSourceLocationService.js +4 -2
  48. package/dist/application/WorkflowEvidence.js +82 -0
  49. package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
  50. package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
  51. package/dist/application/binary/AnalysisSnapshotCache.js +3 -6
  52. package/dist/application/binary/BinarySession.js +95 -68
  53. package/dist/application/binary/BinarySessionOpen.js +3 -3
  54. package/dist/application/binary/BinarySessionRecords.js +25 -3
  55. package/dist/application/binary/BinarySessionStatus.js +17 -1
  56. package/dist/application/binary/CompositeProvider.js +13 -0
  57. package/dist/application/binary/LazyAnalysisProvider.js +3 -0
  58. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
  59. package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
  60. package/dist/application/evm/EvmInterfaceService.js +4 -2
  61. package/dist/application/investigation/EvidenceLedger.js +21 -7
  62. package/dist/application/investigation/InvestigationRecords.js +8 -0
  63. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  64. package/dist/application/javascript/JavaScriptApplicationEvidence.js +24 -3
  65. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  66. package/dist/application/javascript/JavaScriptApplicationService.js +22 -15
  67. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  68. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -4
  69. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
  70. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +6 -3
  71. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +11 -3
  72. package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
  73. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  74. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
  75. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  76. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
  77. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +23 -1
  78. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  79. package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
  80. package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
  81. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  82. package/dist/application/process/ProcessCli.js +14 -6
  83. package/dist/application/process/ProcessEvidence.js +4 -3
  84. package/dist/application/workflowInputError.js +18 -0
  85. package/dist/artifacts/ArtifactProvider.js +12 -2
  86. package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
  87. package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
  88. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
  89. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  90. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  91. package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
  92. package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
  93. package/dist/artifacts/apple/NibArchive.js +81 -14
  94. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  95. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  96. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +13 -8
  97. package/dist/artifacts/inventory/scanCanonical.js +11 -14
  98. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  99. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  100. package/dist/browser/CdpCaptureEventHandlers.js +76 -11
  101. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  102. package/dist/browser/CdpCaptureEvents.js +25 -0
  103. package/dist/browser/CdpConnection.js +30 -11
  104. package/dist/browser/CdpOptionalCommand.js +2 -3
  105. package/dist/browser/CdpPageCapture.js +23 -1
  106. package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
  107. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  108. package/dist/browser/PlaywrightElectronActiveProvider.js +123 -124
  109. package/dist/browser/WebSourceMapFetcher.js +426 -72
  110. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  111. package/dist/browser/history/CaptureFailures.js +37 -1
  112. package/dist/browser/history/CaptureRelease.js +5 -0
  113. package/dist/browser/history/HarCaptureAdapter.js +3 -3
  114. package/dist/browser/history/HarJson.js +3 -2
  115. package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
  116. package/dist/cli/analysisSelector.js +23 -0
  117. package/dist/cli/applicationCommands.js +2 -3
  118. package/dist/cli/coreBinaryCommands.js +70 -12
  119. package/dist/cli/electronCommands.js +7 -6
  120. package/dist/cli/javascriptApplicationAnalysis.js +7 -3
  121. package/dist/cli/jsonOutput.js +4 -99
  122. package/dist/cli/nativeCallCommands.js +2 -3
  123. package/dist/cli/webRuntimeCommands.js +8 -8
  124. package/dist/cli.js +2 -1
  125. package/dist/cliCommandNames.js +0 -1
  126. package/dist/cliJsonInput.js +9 -4
  127. package/dist/config/environment.js +4 -0
  128. package/dist/config/ghidraStartupTimeout.js +17 -0
  129. package/dist/config/mcpResponseBudget.js +22 -0
  130. package/dist/config/parseConfig.js +2 -1
  131. package/dist/contracts/enhancedInputs.js +5 -3
  132. package/dist/contracts/enhancedToolContracts.js +3 -3
  133. package/dist/contracts/hopperMemoryContracts.js +2 -5
  134. package/dist/contracts/javascript/electronToolContracts.js +1 -1
  135. package/dist/contracts/managed/managedToolContracts.js +2 -4
  136. package/dist/contracts/native/nativeToolContracts.js +4 -2
  137. package/dist/contracts/officialToolContracts.js +14 -15
  138. package/dist/contracts/promptContracts.js +3 -3
  139. package/dist/contracts/sessionLifecycleInputs.js +3 -7
  140. package/dist/contracts/sessionStatusContract.js +2 -4
  141. package/dist/contracts/sessionToolContracts.js +4 -6
  142. package/dist/contracts/sessionToolSchemas.js +2 -5
  143. package/dist/contracts/toolContractExamples.js +0 -1
  144. package/dist/contracts/toolContractHelpers.js +4 -1
  145. package/dist/contracts/toolEffects.js +0 -1
  146. package/dist/contracts/toolOutputSchemaGroups.js +28 -27
  147. package/dist/contracts/toolOutputSchemaPrimitives.js +18 -0
  148. package/dist/contracts/toolSchemaMetadata.js +69 -10
  149. package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
  150. package/dist/domain/analysisErrorBase.js +8 -3
  151. package/dist/domain/analysisErrorCore.js +3 -1
  152. package/dist/domain/analysisErrorPresentation.js +72 -17
  153. package/dist/domain/analysisErrorProjection.js +106 -27
  154. package/dist/domain/android/androidAnalysis.js +2 -4
  155. package/dist/domain/android/androidApplication.js +17 -9
  156. package/dist/domain/apple/appleApplication.js +41 -14
  157. package/dist/domain/apple/dyldEnvironment.js +73 -0
  158. package/dist/domain/apple/dylibResolution.js +120 -9
  159. package/dist/domain/apple/dylibResolutionFindings.js +9 -7
  160. package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
  161. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  162. package/dist/domain/apple/keyedArchive.js +9 -1
  163. package/dist/domain/apple/machoContainer.js +54 -0
  164. package/dist/domain/apple/plistNumbers.js +76 -0
  165. package/dist/domain/artifactIdentity.js +29 -0
  166. package/dist/domain/artifactInventoryEvidence.js +19 -24
  167. package/dist/domain/bridgeCandidateProjection.js +71 -0
  168. package/dist/domain/browserCompleteness.js +1 -0
  169. package/dist/domain/browserObservationError.js +24 -5
  170. package/dist/domain/browserScenarioValues.js +2 -6
  171. package/dist/domain/bundleComparison.js +3 -2
  172. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  173. package/dist/domain/canonicalOrdering.js +9 -5
  174. package/dist/domain/changedBehavior.js +6 -6
  175. package/dist/domain/comparisonSourceEvidence.js +40 -0
  176. package/dist/domain/configurationErrors.js +1 -1
  177. package/dist/domain/evidence.js +64 -9
  178. package/dist/domain/evidenceBundle.js +42 -1
  179. package/dist/domain/evidenceErrors.js +12 -1
  180. package/dist/domain/explicitSensitiveFailure.js +17 -1
  181. package/dist/domain/firmware/firmwareAnalysis.js +6 -7
  182. package/dist/domain/hopperErrors.js +23 -2
  183. package/dist/domain/hopperValues.js +51 -8
  184. package/dist/domain/immutableJson.js +114 -0
  185. package/dist/domain/inputIssueProjection.js +3 -0
  186. package/dist/domain/javascript/electronActiveObservation.js +30 -4
  187. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  188. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  189. package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
  190. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  191. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  192. package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
  193. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  194. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  195. package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
  196. package/dist/domain/javascript/javascriptSemanticGraph.js +13 -0
  197. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  198. package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
  199. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  200. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  201. package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
  202. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  203. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  204. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  205. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
  206. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  207. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
  208. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  209. package/dist/domain/jsonSerialization.js +109 -0
  210. package/dist/domain/jsonValue.js +90 -6
  211. package/dist/domain/localPath.js +6 -0
  212. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  213. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  214. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  215. package/dist/domain/managed/managedNativeVerification.js +3 -9
  216. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  217. package/dist/domain/native/nativeCallObservation.js +33 -11
  218. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  219. package/dist/domain/process/processCapture.js +8 -4
  220. package/dist/domain/process/processComparison.js +38 -4
  221. package/dist/domain/process/processScenario.js +11 -10
  222. package/dist/domain/propertyListKeys.js +1 -1
  223. package/dist/domain/propertyListXmlText.js +19 -0
  224. package/dist/domain/providerAdapterError.js +1 -1
  225. package/dist/domain/providerOperationHealth.js +54 -0
  226. package/dist/domain/reconstructionVerification.js +6 -43
  227. package/dist/domain/reconstructionVerificationSchemas.js +2 -2
  228. package/dist/domain/staticRuntimeCorrelation.js +6 -43
  229. package/dist/domain/webBundleAnalysis.js +20 -8
  230. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  231. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  232. package/dist/domain/webRuntime.js +19 -5
  233. package/dist/domain/webSourceLocation.js +1 -0
  234. package/dist/firmware/FirmwareFiles.js +1 -1
  235. package/dist/generatedPackageMetadata.js +1 -1
  236. package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
  237. package/dist/ghidra/GhidraClient.js +47 -14
  238. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  239. package/dist/ghidra/GhidraFunctionValues.js +10 -7
  240. package/dist/ghidra/GhidraInstallation.js +18 -21
  241. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  242. package/dist/ghidra/GhidraJavaLaunch.js +62 -0
  243. package/dist/ghidra/GhidraLauncher.js +33 -16
  244. package/dist/ghidra/GhidraProviderCapabilities.js +14 -2
  245. package/dist/ghidra/GhidraProviderClient.js +23 -12
  246. package/dist/ghidra/GhidraSessionError.js +11 -7
  247. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  248. package/dist/ghidra/GhidraTransport.js +20 -0
  249. package/dist/hopper/BridgeLauncher.js +31 -11
  250. package/dist/hopper/HopperAnalysisProfile.js +62 -4
  251. package/dist/hopper/HopperCleanup.js +15 -3
  252. package/dist/hopper/HopperClient.js +222 -14
  253. package/dist/hopper/HopperFileOffset.js +237 -0
  254. package/dist/hopper/HopperMachOImage.js +196 -0
  255. package/dist/hopper/HopperOperationStage.js +6 -0
  256. package/dist/hopper/HopperProvider.js +63 -9
  257. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  258. package/dist/hopper/HopperRegexSearch.js +137 -0
  259. package/dist/hopper/HopperRegexWorker.js +27 -0
  260. package/dist/hopper/HopperRequestQueue.js +68 -19
  261. package/dist/hopper/HopperTargetLease.js +3 -2
  262. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  263. package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
  264. package/dist/inspector/V8InspectorProvider.js +47 -11
  265. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  266. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
  267. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  268. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  269. package/dist/mcpDoctor.js +62 -2
  270. package/dist/native/AppleDispatchCoverage.js +47 -6
  271. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  272. package/dist/native/AppleDispatchMetadata.js +6 -3
  273. package/dist/native/AppleMachoFixups.js +48 -24
  274. package/dist/native/AppleMachoSelection.js +32 -16
  275. package/dist/native/AppleObjcCategories.js +6 -2
  276. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  277. package/dist/native/AppleObjcProperties.js +2 -1
  278. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  279. package/dist/native/AppleSwiftVtables.js +21 -15
  280. package/dist/native/CommandRunner.js +81 -84
  281. package/dist/native/LldbCallTracer.js +365 -102
  282. package/dist/native/LldbRetainedObservations.js +178 -0
  283. package/dist/native/NativeCallObservation.js +62 -3
  284. package/dist/native/NativeMacOSProvider.js +98 -17
  285. package/dist/native/SignatureTargetBinding.js +155 -0
  286. package/dist/native/parsers/lipo.js +71 -1
  287. package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
  288. package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
  289. package/dist/process/DarwinProcessRunTokenReader.js +8 -9
  290. package/dist/process/ExecFileOutput.js +20 -0
  291. package/dist/process/OwnedCommand.js +7 -2
  292. package/dist/process/ProcessOwnership.js +203 -53
  293. package/dist/process/ProcessOwnershipObservation.js +49 -4
  294. package/dist/process/ProviderProcess.js +38 -7
  295. package/dist/process/capture/ProcessCaptureError.js +2 -2
  296. package/dist/process/capture/ProcessCaptureLifecycle.js +100 -34
  297. package/dist/server/EvidenceMcpServer.js +146 -0
  298. package/dist/server/createServer.js +15 -8
  299. package/dist/server/registerAndroidTools.js +2 -4
  300. package/dist/server/registerApplicationTools/helpers.js +2 -4
  301. package/dist/server/registerArtifactComparisonTool.js +11 -7
  302. package/dist/server/registerBinaryDiagnosticsTools.js +2 -4
  303. package/dist/server/registerBrowserScenarioTool.js +2 -4
  304. package/dist/server/registerBrowserTools.js +2 -4
  305. package/dist/server/registerBundleComparisonTool.js +2 -3
  306. package/dist/server/registerCloseLifecycleTool.js +8 -18
  307. package/dist/server/registerElectronTools.js +2 -4
  308. package/dist/server/registerEnhancedTools.js +18 -59
  309. package/dist/server/registerEvidenceTools.js +2 -4
  310. package/dist/server/registerEvmTools.js +2 -4
  311. package/dist/server/registerFirmwareTools.js +2 -4
  312. package/dist/server/registerFunctionComparisonTool.js +10 -6
  313. package/dist/server/registerInvestigationTools.js +7 -7
  314. package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
  315. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
  316. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
  317. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
  318. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
  319. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
  320. package/dist/server/registerOfficialTools.js +2 -4
  321. package/dist/server/registerProcessComparisonTool.js +71 -45
  322. package/dist/server/registerRecordedCrashTools.js +2 -4
  323. package/dist/server/registerSessionRecordTools.js +5 -6
  324. package/dist/server/registerSessionStatusTool.js +17 -3
  325. package/dist/server/registerSessionTools.js +11 -3
  326. package/dist/server/registerWebModuleTool.js +2 -4
  327. package/dist/server/registerWebNetworkCaptureTool.js +2 -4
  328. package/dist/server/registerWebRuntimeTools.js +3 -7
  329. package/dist/server/registerWebScriptTool.js +2 -4
  330. package/dist/server/registerWebSourceLocationTool.js +2 -4
  331. package/dist/server/runDerivedOperation.js +15 -3
  332. package/dist/server/sessionAvailabilityPolicy.js +0 -1
  333. package/dist/server/toolRegistrationOptions.js +2 -2
  334. package/dist/server/toolResult.js +62 -10
  335. package/dist/server/toolResultEncoding.js +33 -0
  336. package/install.sh +1 -1
  337. package/native/windows/build/manifest.json +1 -1
  338. package/package.json +8 -3
  339. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  340. package/scripts/electron-active-hook.cjs +241 -37
  341. package/skills/reverse-engineer-anything/SKILL.md +11 -3
  342. package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
  343. package/dist/ghidra/GhidraDefaults.js +0 -2
@@ -0,0 +1,196 @@
1
+ import { createHash } from "node:crypto";
2
+ import { open } from "node:fs/promises";
3
+ import { z } from "zod";
4
+ import { BinaryTargetError } from "../domain/configurationErrors.js";
5
+ import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
6
+ import { readFatSliceDeclarations, validateFatSlice, } from "../domain/apple/machoContainer.js";
7
+ import { HopperCancelledError, HopperStartError, } from "../domain/hopperErrors.js";
8
+ import { err, ok } from "../domain/result.js";
9
+ /** Stable source coordinates committed before preparing an owned thin image. */
10
+ export const hopperMachOImageSchema = z.strictObject({
11
+ method: z.literal("fat64_thin_slice"),
12
+ architecture_count: z.number().int().min(1).max(128),
13
+ container_table_sha256: z.string().regex(/^[a-f0-9]{64}$/u),
14
+ source_offset: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
15
+ byte_length: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
16
+ cpu_type: z.number().int().nonnegative(),
17
+ cpu_subtype: z.number().int().nonnegative(),
18
+ });
19
+ /** Validate the selected FAT64 slice without depending on Apple's lipo tool. */
20
+ export const resolveHopperMachOImage = async (target, signal) => {
21
+ const invalid = (reason) => err(new BinaryTargetError(target.path, reason));
22
+ if (signal?.aborted)
23
+ return err(new AnalysisCancelledError("open_binary"));
24
+ let file;
25
+ try {
26
+ file = await open(target.path, "r");
27
+ }
28
+ catch (cause) {
29
+ return invalid(`Cannot read FAT64 source for Hopper image preparation: ${cause instanceof Error ? cause.message : String(cause)}`);
30
+ }
31
+ try {
32
+ const read = async (offset, length) => {
33
+ const bytes = Buffer.alloc(length);
34
+ const { bytesRead } = await file.read(bytes, 0, length, offset);
35
+ return bytes.subarray(0, bytesRead);
36
+ };
37
+ const header = await read(0, 8);
38
+ const magic = header.length === 8 ? header.readUInt32BE(0) : 0;
39
+ if (magic !== 0xcafebabf && magic !== 0xbfbafeca)
40
+ return invalid("FAT64 source header changed before Hopper image preparation");
41
+ const littleEndian = magic === 0xbfbafeca;
42
+ const count = littleEndian
43
+ ? header.readUInt32LE(4)
44
+ : header.readUInt32BE(4);
45
+ const size = (await file.stat()).size;
46
+ const tableEnd = 8 + count * 32;
47
+ if (count === 0 || count > 128 || tableEnd > size)
48
+ return invalid("FAT64 architecture table is truncated or exceeds the supported 128 entries");
49
+ const table = await read(8, count * 32);
50
+ const parsed = readFatSliceDeclarations(table, {
51
+ count,
52
+ wide: true,
53
+ littleEndian,
54
+ });
55
+ if (parsed.status === "malformed")
56
+ return invalid(parsed.reason);
57
+ const cpuTypes = { x86: 7, x86_64: 0x1000007, arm: 12, arm64: 0x100000c };
58
+ const matches = [];
59
+ const ranges = [];
60
+ for (const slice of parsed.slices) {
61
+ if (signal?.aborted)
62
+ return err(new AnalysisCancelledError("open_binary"));
63
+ const rangeError = validateFatSlice(slice, size, tableEnd);
64
+ if (rangeError !== null)
65
+ return invalid(rangeError);
66
+ const reserved = littleEndian
67
+ ? table.readUInt32LE(slice.index * 32 + 28)
68
+ : table.readUInt32BE(slice.index * 32 + 28);
69
+ if (reserved !== 0)
70
+ return invalid(`FAT64 architecture ${slice.index} has a nonzero reserved field`);
71
+ if (slice.size < 12)
72
+ return invalid(`FAT64 architecture ${slice.index} has a truncated Mach-O header`);
73
+ const embedded = await read(slice.offset, 12);
74
+ if (embedded.length !== 12)
75
+ return invalid(`FAT64 architecture ${slice.index} became truncated`);
76
+ const thinMagic = embedded.readUInt32BE(0);
77
+ if (![0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(thinMagic))
78
+ return invalid(`FAT64 architecture ${slice.index} does not contain a Mach-O image`);
79
+ const little = thinMagic === 0xcefaedfe || thinMagic === 0xcffaedfe;
80
+ const identity = {
81
+ cpuType: little ? embedded.readUInt32LE(4) : embedded.readUInt32BE(4),
82
+ cpuSubtype: little
83
+ ? embedded.readUInt32LE(8)
84
+ : embedded.readUInt32BE(8),
85
+ };
86
+ const identityError = validateFatSlice(slice, size, tableEnd, identity);
87
+ if (identityError !== null)
88
+ return invalid(identityError);
89
+ ranges.push(slice);
90
+ if (slice.cpuType === cpuTypes[target.architecture])
91
+ matches.push(slice);
92
+ }
93
+ ranges.sort((a, b) => a.offset - b.offset);
94
+ for (let index = 1; index < ranges.length; index++) {
95
+ const previous = ranges[index - 1];
96
+ const current = ranges[index];
97
+ if (previous !== undefined &&
98
+ current !== undefined &&
99
+ current.offset < previous.offset + previous.size)
100
+ return invalid("FAT64 slices overlap");
101
+ }
102
+ const selected = matches.length === 1 ? matches[0] : undefined;
103
+ if (selected === undefined)
104
+ return invalid(`FAT64 selection for ${target.architecture} is ${matches.length === 0 ? "missing" : "ambiguous"}; extract the exact architecture into a thin image before opening it`);
105
+ return ok({
106
+ method: "fat64_thin_slice",
107
+ architecture_count: count,
108
+ container_table_sha256: createHash("sha256")
109
+ .update(header)
110
+ .update(table)
111
+ .digest("hex"),
112
+ source_offset: selected.offset,
113
+ byte_length: selected.size,
114
+ cpu_type: selected.cpuType,
115
+ cpu_subtype: selected.cpuSubtype,
116
+ });
117
+ }
118
+ catch (cause) {
119
+ return invalid(`Cannot validate FAT64 image: ${cause instanceof Error ? cause.message : String(cause)}`);
120
+ }
121
+ finally {
122
+ await file.close();
123
+ }
124
+ };
125
+ /** Copy a selected slice and verify the entire original source in the same pass. */
126
+ export const prepareHopperMachOImage = async (sourcePath, sourceSha256, image, destination, signal) => {
127
+ if (signal?.aborted)
128
+ return err(new HopperCancelledError());
129
+ try {
130
+ const source = await open(sourcePath, "r");
131
+ try {
132
+ const output = await open(destination, "wx", 0o600);
133
+ try {
134
+ const hash = createHash("sha256");
135
+ const tableHash = createHash("sha256");
136
+ const tableEnd = 8 + image.architecture_count * 32;
137
+ const thinHeader = [];
138
+ let position = 0;
139
+ let copied = 0;
140
+ for await (const chunk of source.createReadStream({
141
+ autoClose: false,
142
+ })) {
143
+ if (signal?.aborted)
144
+ return err(new HopperCancelledError());
145
+ const bytes = Buffer.from(chunk);
146
+ hash.update(bytes);
147
+ if (position < tableEnd)
148
+ tableHash.update(bytes.subarray(0, Math.min(bytes.length, tableEnd - position)));
149
+ const start = Math.max(0, image.source_offset - position);
150
+ const end = Math.min(bytes.length, image.source_offset + image.byte_length - position);
151
+ if (end > start) {
152
+ if (copied < 12)
153
+ thinHeader.push(bytes.subarray(start, Math.min(end, start + 12 - copied)));
154
+ await output.writeFile(bytes.subarray(start, end));
155
+ copied += end - start;
156
+ }
157
+ position += bytes.length;
158
+ }
159
+ const observed = hash.digest("hex");
160
+ const header = Buffer.concat(thinHeader);
161
+ const magic = header.length === 12 ? header.readUInt32BE(0) : 0;
162
+ const little = magic === 0xcefaedfe || magic === 0xcffaedfe;
163
+ const headerMatches = header.length === 12 &&
164
+ [0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(magic) &&
165
+ (little ? header.readUInt32LE(4) : header.readUInt32BE(4)) ===
166
+ image.cpu_type &&
167
+ (little ? header.readUInt32LE(8) : header.readUInt32BE(8)) ===
168
+ image.cpu_subtype;
169
+ if (tableHash.digest("hex") !== image.container_table_sha256 ||
170
+ !headerMatches)
171
+ return err(new HopperStartError({
172
+ userMessage: `FAT64 source ${sourcePath} no longer agrees with its committed architecture table or selected Mach-O header. Open the stable source again.`,
173
+ }));
174
+ if (observed !== sourceSha256 || copied !== image.byte_length)
175
+ return err(new HopperStartError({
176
+ userMessage: `FAT64 source ${sourcePath} changed before launch: expected SHA-256 ${sourceSha256}, observed ${observed}; copied ${copied} of ${image.byte_length} selected bytes. Open the stable source again.`,
177
+ }));
178
+ return ok(destination);
179
+ }
180
+ finally {
181
+ await output.close();
182
+ }
183
+ }
184
+ finally {
185
+ await source.close();
186
+ }
187
+ }
188
+ catch (cause) {
189
+ return signal?.aborted
190
+ ? err(new HopperCancelledError())
191
+ : err(new HopperStartError({
192
+ cause,
193
+ userMessage: `Cannot prepare the selected FAT64 image from ${sourcePath}: ${cause instanceof Error ? cause.message : String(cause)}`,
194
+ }));
195
+ }
196
+ };
@@ -0,0 +1,6 @@
1
+ /** Classify Hopper wire operations at their provider boundary. */
2
+ export const hopperOperationStage = (operation) => {
3
+ if (operation === "health")
4
+ return "connection";
5
+ return operation === "procedure_pseudo_code" ? "decompilation" : "analysis";
6
+ };
@@ -5,7 +5,10 @@ import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.
5
5
  import { err } from "../domain/result.js";
6
6
  import { HopperApplicationLauncher } from "./BridgeLauncher.js";
7
7
  import { hopperLoaderArgsForTarget, resolveHopperAnalysisProfile, } from "./HopperAnalysisProfile.js";
8
+ import { mapHopperFileOffset } from "./HopperFileOffset.js";
9
+ import { HopperRegexSearch } from "./HopperRegexSearch.js";
8
10
  import { HopperClient } from "./HopperClient.js";
11
+ import { hopperMachOImageSchema } from "./HopperMachOImage.js";
9
12
  import { CAPABILITIES, HOPPER_PROVIDER_IDENTITY, } from "./HopperProviderCapabilities.js";
10
13
  export { HOPPER_PROVIDER_IDENTITY, HOPPER_OPERATIONS, } from "./HopperProviderCapabilities.js";
11
14
  const IDENTITY = HOPPER_PROVIDER_IDENTITY;
@@ -111,7 +114,22 @@ export class HopperProvider {
111
114
  execute: (operation) => Promise.resolve(err(new AnalysisCapabilityUnavailableError(IDENTITY.id, operation, `Hopper cannot open ${target.kind} targets directly. Inventory or extract the artifact first.`))),
112
115
  close: () => Promise.resolve(),
113
116
  };
114
- const derivedLoaderArgs = hopperLoaderArgsForTarget(target);
117
+ const preparation = profile?.parameters.prepared_image;
118
+ const parsedImage = preparation === undefined
119
+ ? undefined
120
+ : hopperMachOImageSchema.safeParse(preparation);
121
+ if (parsedImage?.success === false)
122
+ return {
123
+ execute: (operation) => Promise.resolve(err(new AnalysisCapabilityUnavailableError(IDENTITY.id, operation, "Hopper prepared-image profile is malformed; resolve the analysis profile again."))),
124
+ close: () => Promise.resolve(),
125
+ };
126
+ const preparedImage = parsedImage?.data;
127
+ const container = preparedImage === undefined
128
+ ? profile?.parameters.macho_container
129
+ : "thin";
130
+ const derivedLoaderArgs = hopperLoaderArgsForTarget(target, container === "thin" || container === "fat32" || container === "fat64"
131
+ ? container
132
+ : undefined);
115
133
  if (!derivedLoaderArgs.ok)
116
134
  return {
117
135
  execute: () => Promise.resolve(err(derivedLoaderArgs.error)),
@@ -123,6 +141,14 @@ export class HopperProvider {
123
141
  launcherPath: this.config.hopperLauncherPath,
124
142
  targetPath: target.path,
125
143
  targetKind: target.kind,
144
+ ...(preparedImage === undefined
145
+ ? {}
146
+ : {
147
+ preparedImage: {
148
+ image: preparedImage,
149
+ sourceSha256: target.sha256,
150
+ },
151
+ }),
126
152
  loaderArgs: this.config.hopperLoaderArgs.length > 0
127
153
  ? this.config.hopperLoaderArgs
128
154
  : derivedLoaderArgs.value,
@@ -138,25 +164,46 @@ export class HopperProvider {
138
164
  logger: this.logger.child({ layer: "bridge" }),
139
165
  onDiagnostic: (diagnostic) => this.logger.info(diagnostic, "Hopper bridge reported a diagnostic"),
140
166
  });
167
+ const regexSearch = new HopperRegexSearch(client);
141
168
  return {
142
169
  execute: async (operation, parameters, options) => {
143
- const result = await client.callTool(operation, parameters, options);
144
- return result.ok
170
+ const result = (operation === "search_strings" ||
171
+ operation === "search_procedures") &&
172
+ parameters.mode === "regex"
173
+ ? await regexSearch.execute(operation, parameters, options)
174
+ : await client.callTool(operation, parameters, options);
175
+ if (!result.ok)
176
+ return result;
177
+ const mapped = operation === "address_to_file_offset"
178
+ ? await mapHopperFileOffset(target, result.value, options?.signal)
179
+ : result;
180
+ return mapped.ok
145
181
  ? {
146
182
  ok: true,
147
- value: createAnalysisExecution(result.value, executionProvider, {
183
+ value: createAnalysisExecution(mapped.value, executionProvider, {
184
+ rawResult: result.value,
148
185
  ...(profile === undefined ? {} : { analysisProfile: profile }),
149
186
  limitations: [
150
- "Results depend on Hopper's completed static analysis.",
187
+ ...(preparedImage === undefined
188
+ ? []
189
+ : [
190
+ "REA loaded a verified thin Mach-O slice from the original FAT64 source. Identity and file offsets refer to the original file. The owned temporary image and its Hopper document close together, including on MCP shutdown.",
191
+ ]),
192
+ ...(CAPABILITIES.find((descriptor) => descriptor.operation === operation)?.limitations ?? []),
193
+ ...(operation === "read_bytes"
194
+ ? [
195
+ "Hopper byte reads stop at the containing segment's exclusive end; a readable prefix is returned with complete=false when the requested range crosses it.",
196
+ ]
197
+ : []),
151
198
  ...(operation === "procedure_references"
152
199
  ? [
153
- "Hopper's public Python API does not expose flow classification for calls without resolved targets; unresolved_calls is empty and its coverage is unknown.",
200
+ "Native CallReference classifications and unresolved targets are preserved. Detailed reference flags and coverage beyond reported CallReference objects remain unknown.",
154
201
  ]
155
202
  : []),
156
203
  ],
157
204
  }),
158
205
  }
159
- : result;
206
+ : mapped;
160
207
  },
161
208
  runtimeLineageSnapshots: () => {
162
209
  const observation = client.runtimeLineage();
@@ -181,8 +228,15 @@ export class HopperProvider {
181
228
  },
182
229
  ];
183
230
  },
184
- closeWithOutcome: (options) => client.closeWithOutcome(options),
185
- close: () => client.close(),
231
+ operationHealthSnapshot: () => client.operationHealth(),
232
+ closeWithOutcome: async (options) => {
233
+ await regexSearch.close();
234
+ return client.closeWithOutcome(options);
235
+ },
236
+ close: async () => {
237
+ await regexSearch.close();
238
+ await client.close();
239
+ },
186
240
  };
187
241
  }
188
242
  }
@@ -38,7 +38,6 @@ export const HOPPER_OPERATIONS = Object.freeze([
38
38
  "set_addresses_names",
39
39
  "set_bookmark",
40
40
  "set_comment",
41
- "set_current_document",
42
41
  "set_inline_comment",
43
42
  "unset_bookmark",
44
43
  "xrefs",
@@ -69,5 +68,24 @@ export const CAPABILITIES = Object.freeze(HOPPER_OPERATIONS.map((operation) => O
69
68
  }),
70
69
  limitations: Object.freeze([
71
70
  "Results depend on Hopper's completed static analysis.",
71
+ ...(operation === "address_to_file_offset"
72
+ ? [
73
+ "Original-file coordinates require source bytes matching the selected executable digest. A changed, unavailable, or database-only source retains native mapping facts in partial error evidence.",
74
+ ]
75
+ : []),
76
+ ...(operation === "search_strings" || operation === "search_procedures"
77
+ ? [
78
+ "Regex mode uses ECMAScript Unicode semantics in a supervised worker with a five-second matching deadline. Cancellation or deadline failure stops matching without blocking Hopper; literal mode retains native casefold semantics.",
79
+ ]
80
+ : []),
81
+ ...(operation === "list_strings" ||
82
+ operation === "search_strings" ||
83
+ operation === "analyze_function"
84
+ ? [
85
+ "String values cover native typed objects. Hopper may split long literals into adjacent unterminated fragments; string searches match each object independently.",
86
+ "Undecodable typed objects retain native display text with an explicit decoding unknown; these values do not establish decoded source literals.",
87
+ "Reported string encodings are inferred from typed bytes and native display; the original source's intended encoding is unknown.",
88
+ ]
89
+ : []),
72
90
  ]),
73
91
  })));
@@ -0,0 +1,137 @@
1
+ import { Worker } from "node:worker_threads";
2
+ import { z } from "zod";
3
+ import { AnalysisCancelledError, AnalysisOutputError, AnalysisResourceConstraintError, } from "../domain/analysisErrorCore.js";
4
+ import { analysisStringSchema } from "../domain/hopperValues.js";
5
+ import { HopperRemoteError } from "../domain/hopperErrors.js";
6
+ import { err, ok } from "../domain/result.js";
7
+ import { analysisSearchInput } from "../contracts/analysisSearchContract.js";
8
+ const MATCHING_DEADLINE_MS = 5_000;
9
+ const inputSchema = z.strictObject({
10
+ ...analysisSearchInput,
11
+ mode: z.literal("regex"),
12
+ document: z.string().nullish(),
13
+ case_sensitive: z
14
+ .boolean()
15
+ .nullish()
16
+ .transform((value) => value ?? false),
17
+ });
18
+ const replySchema = z.discriminatedUnion("status", [
19
+ z.strictObject({
20
+ status: z.literal("matched"),
21
+ indices: z.array(z.number().int().nonnegative()),
22
+ }),
23
+ z.strictObject({ status: z.literal("invalid_pattern"), reason: z.string() }),
24
+ ]);
25
+ /** Match collected native facts off Hopper's API thread, with cancellable lifetime. */
26
+ export class HopperRegexSearch {
27
+ client;
28
+ #active = new Map();
29
+ constructor(client) {
30
+ this.client = client;
31
+ }
32
+ execute(operation, parameters, options) {
33
+ const controller = new AbortController();
34
+ const signal = options?.signal === undefined
35
+ ? controller.signal
36
+ : AbortSignal.any([controller.signal, options.signal]);
37
+ const pending = this.#execute(operation, parameters, {
38
+ ...options,
39
+ signal,
40
+ });
41
+ this.#active.set(controller, pending);
42
+ void pending.then(() => this.#active.delete(controller), () => this.#active.delete(controller));
43
+ return pending;
44
+ }
45
+ /** Abort matching workers before their provider session closes. */
46
+ async close() {
47
+ for (const controller of this.#active.keys())
48
+ controller.abort();
49
+ await Promise.all(this.#active.values());
50
+ }
51
+ async #execute(operation, parameters, options) {
52
+ const input = inputSchema.safeParse(parameters);
53
+ if (!input.success)
54
+ return err(new HopperRemoteError(-32000, `Invalid search arguments: ${input.error.message}`, { diagnosticType: "invalid_request", operation }));
55
+ const inventoryOptions = {
56
+ ...options,
57
+ ...(options.progress === undefined
58
+ ? {}
59
+ : {
60
+ progress: {
61
+ report: (update) => options.progress?.report({
62
+ ...update,
63
+ completed: update.total === null || update.total === 0
64
+ ? 0
65
+ : Math.min(0.5, update.completed / update.total / 2),
66
+ total: 1,
67
+ }) ?? Promise.resolve(),
68
+ },
69
+ }),
70
+ };
71
+ const inventory = await this.client.callTool(operation === "search_strings" ? "list_strings" : "list_procedures", input.data.document == null ? {} : { document: input.data.document }, inventoryOptions);
72
+ if (!inventory.ok)
73
+ return inventory;
74
+ const parsed = z.array(analysisStringSchema).safeParse(inventory.value);
75
+ if (!parsed.success)
76
+ return err(new AnalysisOutputError(operation, "Hopper search inventory is malformed"));
77
+ if (options.signal?.aborted)
78
+ return err(new AnalysisCancelledError(operation));
79
+ await options.progress
80
+ ?.report({
81
+ phase: "hopper_regex",
82
+ completed: 0.5,
83
+ total: 1,
84
+ message: "Matching inventory in cancellable regex worker",
85
+ })
86
+ .catch(() => undefined);
87
+ if (options.signal?.aborted)
88
+ return err(new AnalysisCancelledError(operation));
89
+ let worker;
90
+ try {
91
+ worker = new Worker(new URL("./HopperRegexWorker.js", import.meta.url), {
92
+ workerData: {
93
+ pattern: input.data.pattern,
94
+ caseSensitive: input.data.case_sensitive,
95
+ values: parsed.data.map((item) => item.value),
96
+ },
97
+ });
98
+ }
99
+ catch (cause) {
100
+ return err(new AnalysisOutputError(operation, `Cannot start regex worker: ${cause instanceof Error ? cause.message : String(cause)}`, { cause }));
101
+ }
102
+ try {
103
+ return await new Promise((resolve) => {
104
+ const finish = (result) => {
105
+ clearTimeout(timer);
106
+ options.signal?.removeEventListener("abort", onAbort);
107
+ resolve(result);
108
+ };
109
+ const onAbort = () => finish(err(new AnalysisCancelledError(operation)));
110
+ const timer = setTimeout(() => finish(err(new AnalysisResourceConstraintError(operation, "cpu", "Regex matching exceeded its supervised deadline; the Hopper API thread remains available.", { matching_deadline_ms: MATCHING_DEADLINE_MS }, {
111
+ remediationAction: "Simplify the ECMAScript Unicode regex or use literal mode, then retry in the same session.",
112
+ }))), MATCHING_DEADLINE_MS);
113
+ options.signal?.addEventListener("abort", onAbort, { once: true });
114
+ if (options.signal?.aborted)
115
+ onAbort();
116
+ worker.once("message", (message) => {
117
+ const reply = replySchema.safeParse(message);
118
+ if (!reply.success)
119
+ return finish(err(new AnalysisOutputError(operation, "Regex worker reply is malformed")));
120
+ if (reply.data.status === "invalid_pattern")
121
+ return finish(err(new HopperRemoteError(-32000, `Invalid regex pattern: ${reply.data.reason}`, { diagnosticType: "invalid_request", operation })));
122
+ const indices = reply.data.indices;
123
+ if (indices.some((index, position) => index >= parsed.data.length ||
124
+ (position > 0 && index <= (indices[position - 1] ?? -1))))
125
+ return finish(err(new AnalysisOutputError(operation, "Regex worker returned invalid inventory indices")));
126
+ const selected = new Set(indices);
127
+ finish(ok(parsed.data.filter((_, index) => selected.has(index))));
128
+ });
129
+ worker.once("error", (cause) => finish(err(new AnalysisOutputError(operation, `Regex worker failed: ${cause.message}`, { cause }))));
130
+ worker.once("exit", (code) => finish(err(new AnalysisOutputError(operation, `Regex worker exited without a result (${code})`))));
131
+ });
132
+ }
133
+ finally {
134
+ await worker.terminate();
135
+ }
136
+ }
137
+ }
@@ -0,0 +1,27 @@
1
+ import { parentPort, workerData } from "node:worker_threads";
2
+ import { z } from "zod";
3
+ const input = z
4
+ .strictObject({
5
+ pattern: z.string().min(1),
6
+ caseSensitive: z.boolean(),
7
+ values: z.array(z.string()),
8
+ })
9
+ .parse(workerData);
10
+ let expression;
11
+ try {
12
+ expression = new RegExp(input.pattern, input.caseSensitive ? "u" : "iu");
13
+ }
14
+ catch (cause) {
15
+ parentPort?.postMessage({
16
+ status: "invalid_pattern",
17
+ reason: cause instanceof Error ? cause.message : String(cause),
18
+ });
19
+ }
20
+ if (expression !== undefined) {
21
+ const indices = [];
22
+ for (const [index, value] of input.values.entries()) {
23
+ if (expression.test(value))
24
+ indices.push(index);
25
+ }
26
+ parentPort?.postMessage({ status: "matched", indices });
27
+ }