rea-agents 3.0.0 → 3.2.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 (628) hide show
  1. package/README.md +83 -108
  2. package/bridge/ghidra/ReaGhidraBridge.java +609 -841
  3. package/bridge/hopper_bridge.py +99 -344
  4. package/dist/application/AbortablePromise.js +6 -3
  5. package/dist/application/AnalysisContextQueries.js +21 -9
  6. package/dist/application/AnalysisSnapshotCache.js +0 -1
  7. package/dist/application/AnalysisSnapshotFiles.js +7 -7
  8. package/dist/application/AndroidApplicationService.js +1 -1
  9. package/dist/application/AppleApplicationService.js +1 -1
  10. package/dist/application/ArtifactExtraction.js +35 -54
  11. package/dist/application/ArtifactExtractionDestination.js +17 -0
  12. package/dist/application/ArtifactGraphConstruction.js +2 -17
  13. package/dist/application/ArtifactInventory/classify.js +2 -6
  14. package/dist/application/ArtifactInventory/hash.js +2 -20
  15. package/dist/application/ArtifactInventory/policy.js +17 -0
  16. package/dist/application/ArtifactInventory/reader.js +1 -4
  17. package/dist/application/ArtifactInventory/scanCanonical.js +8 -15
  18. package/dist/application/ArtifactInventory/scanReader.js +76 -58
  19. package/dist/application/ArtifactInventory/types.js +1 -5
  20. package/dist/application/ArtifactInventory.js +6 -14
  21. package/dist/application/AuthorizedArtifactInventory.js +3 -13
  22. package/dist/application/BinarySession.js +54 -28
  23. package/dist/application/BinarySessionComposition.js +0 -11
  24. package/dist/application/BinarySessionOpen.js +2 -1
  25. package/dist/application/BinarySessionRecords.js +24 -86
  26. package/dist/application/BinarySessionStatus.js +16 -21
  27. package/dist/application/BinaryTargetResolver.js +216 -0
  28. package/dist/application/BrowserEvidence.js +39 -57
  29. package/dist/application/BrowserObservationService.js +3 -6
  30. package/dist/application/BrowserScenarioCaptureService.js +3 -6
  31. package/dist/application/BrowserScenarioEvidence.js +3 -3
  32. package/dist/application/CallPathTracing.js +2 -36
  33. package/dist/application/CapabilityClientRequirements.js +26 -0
  34. package/dist/application/CapabilityInventory.js +143 -77
  35. package/dist/application/ClientConfigurationDocument.js +27 -0
  36. package/dist/application/ClientRegistrationStatus.js +16 -13
  37. package/dist/application/CommandShimReplay.js +14 -1
  38. package/dist/application/DirectAnalysis.js +22 -46
  39. package/dist/application/DirectAnalysisStatus.js +5 -61
  40. package/dist/application/Doctor.js +11 -32
  41. package/dist/application/DoctorDiagnostics.js +1 -2
  42. package/dist/application/DoctorScope.js +1 -1
  43. package/dist/application/ElectronActiveEvidence.js +50 -0
  44. package/dist/application/ElectronActiveObservationPort.js +1 -0
  45. package/dist/application/ElectronActiveObservationService.js +78 -0
  46. package/dist/application/ElectronBoundaryAnalysis.js +7 -8
  47. package/dist/application/ElectronBoundaryGraphContext.js +1 -1
  48. package/dist/application/ElectronBoundaryGraphIpc.js +3 -3
  49. package/dist/application/ElectronBoundaryGraphNative.js +1 -2
  50. package/dist/application/ElectronBoundaryGraphWindows.js +6 -8
  51. package/dist/application/ElectronEvidence.js +4 -7
  52. package/dist/application/ElectronObservationService.js +5 -9
  53. package/dist/application/EnhancedLiteralTracing.js +42 -65
  54. package/dist/application/EnhancedTools.js +98 -64
  55. package/dist/application/EvidenceBundleCommands.js +16 -12
  56. package/dist/application/EvidenceBundleFiles.js +9 -15
  57. package/dist/application/EvidenceLedger.js +14 -42
  58. package/dist/application/FilesystemSnapshot.js +2 -3
  59. package/dist/application/InterfaceBuilderAnalysis.js +266 -0
  60. package/dist/application/InventoryProjectionEvidence.js +4 -2
  61. package/dist/application/InvestigationProviders.js +1 -1
  62. package/dist/application/JavaScriptApplicationEvidence.js +2 -5
  63. package/dist/application/JavaScriptApplicationEvidenceGraph.js +6 -10
  64. package/dist/application/JavaScriptApplicationService.js +6 -29
  65. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +5 -5
  66. package/dist/application/JavaScriptApplicationWorkflowService.js +0 -8
  67. package/dist/application/JavaScriptArtifactAnalysis.js +38 -127
  68. package/dist/application/JavaScriptArtifactFiles.js +67 -107
  69. package/dist/application/JavaScriptArtifactGraphAccumulator.js +0 -7
  70. package/dist/application/JavaScriptArtifactGraphBuilder.js +7 -58
  71. package/dist/application/JavaScriptArtifactGraphBundlers.js +1 -6
  72. package/dist/application/JavaScriptArtifactGraphContext.js +12 -39
  73. package/dist/application/JavaScriptArtifactGraphDocuments.js +4 -11
  74. package/dist/application/JavaScriptArtifactGraphEvidence.js +0 -14
  75. package/dist/application/JavaScriptArtifactGraphFindings.js +3 -3
  76. package/dist/application/JavaScriptArtifactGraphStructure.js +16 -17
  77. package/dist/application/JavaScriptArtifactPathResolution.js +61 -49
  78. package/dist/application/JavaScriptArtifactReconstruction.js +5 -10
  79. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -14
  80. package/dist/application/JavaScriptJsonModules.js +2 -2
  81. package/dist/application/JavaScriptModuleRelationships.js +22 -27
  82. package/dist/application/JavaScriptReplayPermission.js +1 -1
  83. package/dist/application/JavaScriptReplayPlanning.js +9 -3
  84. package/dist/application/JavaScriptReplayService.js +29 -47
  85. package/dist/application/JavaScriptReturnShapeProjection.js +12 -42
  86. package/dist/application/JavaScriptRuntimeObservationEvidence.js +7 -8
  87. package/dist/application/JavaScriptRuntimeObservationService.js +4 -8
  88. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +2 -3
  89. package/dist/application/JavaScriptSemanticGraphBuilder.js +11 -41
  90. package/dist/application/JavaScriptSemanticGraphConstruction.js +5 -29
  91. package/dist/application/JavaScriptSemanticGraphEvidence.js +1 -1
  92. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +1 -1
  93. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +0 -13
  94. package/dist/application/JavaScriptSemanticGraphProjection.js +1 -3
  95. package/dist/application/JavaScriptSemanticTraceService.js +1 -10
  96. package/dist/application/JsonFiles.js +79 -0
  97. package/dist/application/LinuxHopper.js +11 -9
  98. package/dist/application/LoopbackReplay.js +26 -23
  99. package/dist/application/LoopbackReplayRecorder.js +29 -1
  100. package/dist/application/ManagedApplicationGraphService.js +1 -2
  101. package/dist/application/ManagedMemberComparisonService.js +11 -41
  102. package/dist/application/ManagedNativeVerificationService.js +1 -2
  103. package/dist/application/ManagedReconstructionService.js +1 -1
  104. package/dist/application/ManagedRuntimeCorrelationService.js +14 -13
  105. package/dist/application/NativeApiInspection.js +2 -7
  106. package/dist/application/NativeUiActionTrace.js +394 -0
  107. package/dist/application/NodeRuntimeCharacterizationService.js +11 -16
  108. package/dist/application/PermissionAuthority.js +15 -7
  109. package/dist/application/PermissionFailure.js +5 -0
  110. package/dist/application/ProcessCaptureAuthority.js +5 -7
  111. package/dist/application/ProcessCaptureJournal.js +3 -2
  112. package/dist/application/ProcessCaptureLifecycle.js +10 -12
  113. package/dist/application/ProcessCheckpoints.js +29 -11
  114. package/dist/application/ProcessCli.js +8 -17
  115. package/dist/application/ProcessEvidence.js +5 -7
  116. package/dist/application/ProcessHarness.js +60 -20
  117. package/dist/application/ProcessNormalization.js +2 -1
  118. package/dist/application/ProcessReactiveCoordinator.js +2 -4
  119. package/dist/application/ProcessReactiveEffects.js +9 -3
  120. package/dist/application/ProcessReactiveHarness.js +13 -7
  121. package/dist/application/ProcessSampling.js +2 -4
  122. package/dist/application/ProcessTimer.js +39 -0
  123. package/dist/application/ProjectPermissionStore.js +39 -95
  124. package/dist/application/RealHopperAssertions.js +20 -66
  125. package/dist/application/ReconstructionCoverageService.js +12 -58
  126. package/dist/application/ReconstructionObligationAuthority.js +2 -2
  127. package/dist/application/ReconstructionObligationCandidates.js +4 -4
  128. package/dist/application/ReconstructionObligationLedgerEvaluation.js +8 -15
  129. package/dist/application/ReconstructionObligationLedgerProjection.js +3 -7
  130. package/dist/application/ReconstructionObligationLedgerService.js +19 -38
  131. package/dist/application/ReferenceSourceImport.js +21 -47
  132. package/dist/application/ReferenceSourceImportEntries.js +2 -4
  133. package/dist/application/ReferenceSourceImportPolicy.js +5 -32
  134. package/dist/application/ReferenceSourceImportTypes.js +0 -16
  135. package/dist/application/RuntimeExecutableDiagnostics.js +55 -29
  136. package/dist/application/SessionProviderRouter.js +2 -2
  137. package/dist/application/Setup.js +1 -3
  138. package/dist/application/SetupClientConfiguration.js +22 -88
  139. package/dist/application/SetupRegistrationEnvironment.js +0 -7
  140. package/dist/application/StoreFileLock.js +119 -0
  141. package/dist/application/TerminalRenderer.js +2 -3
  142. package/dist/application/Uninstall.js +9 -14
  143. package/dist/application/UnknownEvidence.js +1 -1
  144. package/dist/application/WindowsCapabilities.js +5 -4
  145. package/dist/artifacts/ArtifactPaths.js +2 -5
  146. package/dist/artifacts/ArtifactProvider.js +43 -67
  147. package/dist/artifacts/DirectoryArtifactReader.js +13 -8
  148. package/dist/artifacts/MachOSliceArtifactReader.js +1 -5
  149. package/dist/artifacts/NativeDmgArtifactReader.js +11 -11
  150. package/dist/artifacts/NibArchive.js +269 -0
  151. package/dist/artifacts/SafeOutputTree.js +21 -31
  152. package/dist/browser/BrowserProcessStartup.js +1 -2
  153. package/dist/browser/CdpAuthorizedMainFrame.js +16 -0
  154. package/dist/browser/CdpBrowserProvider.js +3 -13
  155. package/dist/browser/CdpCanonicalJsonDigest.js +9 -0
  156. package/dist/browser/CdpCaptureDocuments.js +28 -76
  157. package/dist/browser/CdpCaptureEventBodyShapes.js +13 -33
  158. package/dist/browser/CdpCaptureEventHandlers.js +22 -87
  159. package/dist/browser/CdpCaptureEvents.js +2 -8
  160. package/dist/browser/CdpCaptureStorage.js +9 -20
  161. package/dist/browser/CdpCaptureStorageFingerprints.js +85 -95
  162. package/dist/browser/CdpCaptureValues.js +21 -21
  163. package/dist/browser/CdpConnection.js +10 -25
  164. package/dist/browser/CdpElectronInspection.js +29 -51
  165. package/dist/browser/CdpElectronProvider.js +10 -35
  166. package/dist/browser/CdpElectronScriptEvents.js +8 -16
  167. package/dist/browser/CdpElectronScripts.js +6 -35
  168. package/dist/browser/CdpElectronWorkers.js +6 -10
  169. package/dist/browser/CdpEndpoint.js +25 -41
  170. package/dist/browser/CdpObservationSession.js +14 -26
  171. package/dist/browser/CdpPageCapture.js +34 -48
  172. package/dist/browser/CdpPageCaptureScripts.js +1 -19
  173. package/dist/browser/CdpPageCaptureWorkers.js +6 -10
  174. package/dist/browser/CdpSafeMetadata.js +19 -22
  175. package/dist/browser/CdpScreenshot.js +3 -5
  176. package/dist/browser/CdpTargetSession.js +1 -2
  177. package/dist/browser/CdpWebMcpDiscovery.js +13 -22
  178. package/dist/browser/ElectronFileScope.js +8 -19
  179. package/dist/browser/JavaScriptRuntimeScope.js +10 -10
  180. package/dist/browser/PlaywrightBrowserScenarioProvider.js +31 -64
  181. package/dist/browser/PlaywrightElectronActiveActions.js +309 -0
  182. package/dist/browser/PlaywrightElectronActiveProvider.js +274 -0
  183. package/dist/browser/PlaywrightExecutionBoundary.js +16 -5
  184. package/dist/browser/PlaywrightScenarioActions.js +3 -7
  185. package/dist/browser/PlaywrightScenarioArtifacts.js +23 -92
  186. package/dist/browser/PlaywrightScenarioBrowser.js +7 -9
  187. package/dist/browser/PlaywrightScenarioEvents.js +45 -94
  188. package/dist/browser/PlaywrightScenarioSession.js +18 -34
  189. package/dist/browser/PngVisualDiff.js +22 -14
  190. package/dist/browser/SensitiveTextCapture.js +1 -18
  191. package/dist/browser/V8InspectorCaptureProjection.js +7 -7
  192. package/dist/browser/V8InspectorEndpoint.js +12 -14
  193. package/dist/browser/V8InspectorProvider.js +20 -61
  194. package/dist/browser/WebSourceMapFetcher.js +56 -176
  195. package/dist/catalogIdentity.js +12 -60
  196. package/dist/cli/artifactCommands.js +49 -77
  197. package/dist/cli/coreAnalysisCommands.js +83 -133
  198. package/dist/cli/javascriptApplicationAnalysis.js +1 -9
  199. package/dist/cli/managedCommands.js +6 -271
  200. package/dist/cli/setupCommands.js +3 -12
  201. package/dist/cli/utilityCommands.js +7 -41
  202. package/dist/cli.js +0 -2
  203. package/dist/cliApplicationCommands.js +44 -114
  204. package/dist/cliBrowserAdvancedCommands.js +12 -102
  205. package/dist/cliBrowserCommands.js +19 -124
  206. package/dist/cliBrowserContext.js +30 -0
  207. package/dist/cliCommandNames.js +5 -5
  208. package/dist/cliElectronCommands.js +49 -71
  209. package/dist/cliEvidenceCommands.js +8 -77
  210. package/dist/cliJavaScriptRuntimeCommands.js +18 -92
  211. package/dist/cliJsonInput.js +4 -14
  212. package/dist/cliObservationOptions.js +11 -92
  213. package/dist/cliPolicyCommands.js +2 -16
  214. package/dist/cliProcessCommands.js +3 -3
  215. package/dist/cliSetup.js +0 -13
  216. package/dist/config/browserScenario.js +77 -0
  217. package/dist/config/electronAutomation.js +35 -0
  218. package/dist/config/environment.js +6 -9
  219. package/dist/config/javascriptReplay.js +41 -0
  220. package/dist/config/managedRuntime.js +25 -0
  221. package/dist/config/parseConfig.js +56 -232
  222. package/dist/config/parsers.js +16 -28
  223. package/dist/config/passiveObservation.js +87 -0
  224. package/dist/config/permissions.js +0 -7
  225. package/dist/config/processCapture.js +47 -0
  226. package/dist/contracts/analysisSearchContract.js +2 -5
  227. package/dist/contracts/applicationToolContracts.js +58 -114
  228. package/dist/contracts/applicationWorkflowInputContracts.js +29 -114
  229. package/dist/contracts/artifactComparisonExample.js +58 -60
  230. package/dist/contracts/artifactToolContracts.js +37 -91
  231. package/dist/contracts/browserScenarioToolContracts.js +6 -51
  232. package/dist/contracts/browserToolContracts.js +10 -75
  233. package/dist/contracts/electronToolContracts.js +27 -98
  234. package/dist/contracts/enhancedInputs.js +31 -78
  235. package/dist/contracts/errorSchemas.js +0 -1
  236. package/dist/contracts/functionComparisonExample.js +10 -24
  237. package/dist/contracts/functionInstructionContract.js +1 -3
  238. package/dist/contracts/functionWorkflowToolContracts.js +4 -5
  239. package/dist/contracts/hopperMemoryContracts.js +3 -3
  240. package/dist/contracts/investigationExamples.js +14 -11
  241. package/dist/contracts/javascriptApplicationWorkflowExamples.js +12 -19
  242. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +2 -20
  243. package/dist/contracts/javascriptRuntimeReconciliationExample.js +45 -12
  244. package/dist/contracts/managedToolContracts.js +10 -104
  245. package/dist/contracts/managedWorkflowExamples.js +77 -125
  246. package/dist/contracts/managedWorkflowToolContracts.js +51 -74
  247. package/dist/contracts/nativeToolContracts.js +9 -14
  248. package/dist/contracts/processCaptureExample.js +2 -69
  249. package/dist/contracts/promptContracts.js +49 -67
  250. package/dist/contracts/providerSelection.js +0 -1
  251. package/dist/contracts/reconstructionReadinessExample.js +1 -6
  252. package/dist/contracts/sessionStatusContract.js +1 -17
  253. package/dist/contracts/sessionToolSchemas.js +52 -0
  254. package/dist/contracts/toolContractExamples.js +11 -10
  255. package/dist/contracts/toolContractHelpers.js +19 -0
  256. package/dist/contracts/toolContracts.js +60 -143
  257. package/dist/contracts/toolEffects.js +16 -9
  258. package/dist/contracts/toolOutputSchemaGroups.js +47 -86
  259. package/dist/contracts/toolOutputSchemaPrimitives.js +72 -62
  260. package/dist/contracts/toolSchemaMetadata.js +117 -0
  261. package/dist/contracts/unknownContractExamples.js +0 -2
  262. package/dist/doctorRuntime.js +1 -1
  263. package/dist/domain/analysisErrorPresentation.js +46 -54
  264. package/dist/domain/analysisErrorProjection.js +28 -37
  265. package/dist/domain/analysisProfile.js +3 -31
  266. package/dist/domain/analysisSnapshot.js +3 -12
  267. package/dist/domain/androidApplication.js +15 -52
  268. package/dist/domain/appleApplication.js +24 -65
  269. package/dist/domain/artifactComparison.js +11 -29
  270. package/dist/domain/artifactGraph.js +14 -44
  271. package/dist/domain/artifactInspection.js +38 -69
  272. package/dist/domain/artifactInventoryEvidence.js +27 -21
  273. package/dist/domain/binaryTarget.js +2 -219
  274. package/dist/domain/binaryTargetTypes.js +1 -0
  275. package/dist/domain/browserCaptureComparison.js +35 -60
  276. package/dist/domain/browserObservation.js +45 -197
  277. package/dist/domain/browserObservationSchemas.js +5 -23
  278. package/dist/domain/browserScenario.js +11 -14
  279. package/dist/domain/browserScenarioCapture.js +11 -12
  280. package/dist/domain/browserScenarioCaptureValues.js +146 -84
  281. package/dist/domain/browserScenarioDiff.js +2 -59
  282. package/dist/domain/browserScenarioDiffEvidence.js +51 -0
  283. package/dist/domain/browserScenarioDiffValues.js +21 -38
  284. package/dist/domain/browserScenarioValues.js +80 -109
  285. package/dist/domain/browserSession.js +4 -7
  286. package/dist/domain/bundleComparison.js +6 -32
  287. package/dist/domain/bytecodeProvider.js +53 -54
  288. package/dist/domain/callPath.js +50 -169
  289. package/dist/domain/callPathSchemas.js +79 -0
  290. package/dist/domain/changedBehavior.js +34 -60
  291. package/dist/domain/completionLedgerGeneration.js +8 -14
  292. package/dist/domain/conformancePackage.js +126 -97
  293. package/dist/domain/conformanceReplay.js +39 -11
  294. package/dist/domain/conformanceTrustGate.js +174 -30
  295. package/dist/domain/customProtocolCapture.js +4 -4
  296. package/dist/domain/electronActiveObservation.js +244 -0
  297. package/dist/domain/electronObservation.js +21 -83
  298. package/dist/domain/electronStaticAnalysisBrowser.js +36 -46
  299. package/dist/domain/electronStaticAnalysisIpc.js +38 -14
  300. package/dist/domain/electronStaticAnalysisNative.js +1 -8
  301. package/dist/domain/electronStaticAnalysisValues.js +14 -18
  302. package/dist/domain/errors.js +33 -54
  303. package/dist/domain/eventProcessTree.js +101 -90
  304. package/dist/domain/evidence.js +2 -10
  305. package/dist/domain/evidenceBundle.js +3 -5
  306. package/dist/domain/evidenceCompletionLedger.js +6 -8
  307. package/dist/domain/functionComparison.js +4 -14
  308. package/dist/domain/functionComparisonNormalization.js +8 -8
  309. package/dist/domain/functionComparisonResults.js +25 -15
  310. package/dist/domain/functionComparisonSchemas.js +49 -33
  311. package/dist/domain/functionDossierEvidence.js +31 -151
  312. package/dist/domain/hopperStartupFailure.js +1 -1
  313. package/dist/domain/hopperValues.js +17 -141
  314. package/dist/domain/inputIssueProjection.js +4 -1
  315. package/dist/domain/interfaceBuilderGraph.js +654 -0
  316. package/dist/domain/javascriptApplicationAnalysis.js +8 -112
  317. package/dist/domain/javascriptApplicationChangeGraph.js +22 -82
  318. package/dist/domain/javascriptApplicationEvidenceSchemas.js +59 -47
  319. package/dist/domain/javascriptApplicationGraph.js +3 -13
  320. package/dist/domain/javascriptApplicationGraphSchemas.js +12 -34
  321. package/dist/domain/javascriptApplicationVersionComparison.js +26 -30
  322. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +123 -68
  323. package/dist/domain/javascriptApplicationVersionItems.js +120 -53
  324. package/dist/domain/javascriptApplicationVersionKeys.js +24 -11
  325. package/dist/domain/javascriptAstFingerprint.js +25 -58
  326. package/dist/domain/javascriptAstValues.js +9 -0
  327. package/dist/domain/javascriptExportInstrumentation.js +2 -4
  328. package/dist/domain/javascriptExportShapeComparison.js +6 -7
  329. package/dist/domain/javascriptExportShapeComparisonSchemas.js +70 -77
  330. package/dist/domain/javascriptExportShapeSelection.js +17 -19
  331. package/dist/domain/javascriptFeatureSeed.js +20 -12
  332. package/dist/domain/javascriptFeatureTrace.js +13 -67
  333. package/dist/domain/javascriptFeatureTraceSchemas.js +24 -52
  334. package/dist/domain/javascriptFeatureTraversal.js +1 -44
  335. package/dist/domain/javascriptNativeHandoff.js +1 -1
  336. package/dist/domain/javascriptReplay.js +100 -101
  337. package/dist/domain/javascriptRuntimeLoadState.js +3 -8
  338. package/dist/domain/javascriptRuntimeObservation.js +43 -103
  339. package/dist/domain/javascriptRuntimeReconciliation.js +1 -3
  340. package/dist/domain/javascriptRuntimeReconciliationActive.js +80 -0
  341. package/dist/domain/javascriptRuntimeReconciliationGraph.js +21 -33
  342. package/dist/domain/javascriptRuntimeReconciliationMatching.js +75 -61
  343. package/dist/domain/javascriptRuntimeReconciliationParsing.js +21 -46
  344. package/dist/domain/javascriptRuntimeReconciliationResult.js +25 -19
  345. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +8 -12
  346. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +34 -49
  347. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -3
  348. package/dist/domain/javascriptSemanticAnalysis.js +12 -45
  349. package/dist/domain/javascriptSemanticAsyncEffects.js +1 -9
  350. package/dist/domain/javascriptSemanticCallResolution.js +6 -16
  351. package/dist/domain/javascriptSemanticCalls.js +5 -32
  352. package/dist/domain/javascriptSemanticChildProcesses.js +1 -11
  353. package/dist/domain/javascriptSemanticCoverage.js +11 -0
  354. package/dist/domain/javascriptSemanticDataEffectHelpers.js +1 -8
  355. package/dist/domain/javascriptSemanticDataEffects.js +1 -11
  356. package/dist/domain/javascriptSemanticFingerprints.js +3 -5
  357. package/dist/domain/javascriptSemanticGraphSchemas.js +25 -51
  358. package/dist/domain/javascriptSemanticGraphSerialization.js +2 -13
  359. package/dist/domain/javascriptSemanticIr.js +1 -29
  360. package/dist/domain/javascriptSemanticObjects.js +1 -5
  361. package/dist/domain/javascriptSemanticPrimitives.js +2 -9
  362. package/dist/domain/javascriptSemanticProjection.js +0 -18
  363. package/dist/domain/javascriptSemanticPromises.js +9 -16
  364. package/dist/domain/javascriptSemanticProvenance.js +16 -19
  365. package/dist/domain/javascriptSemanticQuery.js +17 -139
  366. package/dist/domain/javascriptSemanticQueryAssessment.js +9 -37
  367. package/dist/domain/javascriptSemanticQueryIdentity.js +2 -23
  368. package/dist/domain/javascriptSemanticQuerySchemas.js +14 -107
  369. package/dist/domain/javascriptSemanticResources.js +1 -6
  370. package/dist/domain/javascriptSemanticReturns.js +10 -27
  371. package/dist/domain/javascriptSemanticValueTypes.js +1 -0
  372. package/dist/domain/javascriptSemanticValues.js +44 -62
  373. package/dist/domain/javascriptStaticAnalysis.js +21 -43
  374. package/dist/domain/javascriptStaticAnalysisBundler.js +34 -93
  375. package/dist/domain/javascriptStaticAnalysisCalls.js +17 -16
  376. package/dist/domain/javascriptStaticAnalysisFindings.js +3 -19
  377. package/dist/domain/javascriptStaticAnalysisHelpers.js +47 -88
  378. package/dist/domain/javascriptStaticAnalysisState.js +1 -5
  379. package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
  380. package/dist/domain/jsonShape.js +7 -33
  381. package/dist/domain/localPath.js +7 -0
  382. package/dist/domain/managedApplicationGraph.js +9 -41
  383. package/dist/domain/managedApplicationGraphCoverage.js +24 -156
  384. package/dist/domain/managedApplicationGraphNodes.js +10 -13
  385. package/dist/domain/managedArtifact.js +14 -27
  386. package/dist/domain/managedMemberComparison.js +90 -92
  387. package/dist/domain/managedMemberComparisonCoverage.js +11 -33
  388. package/dist/domain/managedMemberComparisonItems.js +221 -0
  389. package/dist/domain/managedMemberComparisonMatch.js +8 -208
  390. package/dist/domain/managedNativeVerification.js +3 -6
  391. package/dist/domain/managedNativeVerificationMatch.js +55 -59
  392. package/dist/domain/managedNativeVerificationSchemas.js +83 -47
  393. package/dist/domain/managedReconstruction.js +19 -23
  394. package/dist/domain/managedRuntimeCorrelation.js +6 -9
  395. package/dist/domain/nativeApiBoundary.js +17 -14
  396. package/dist/domain/nativeInspection.js +0 -2
  397. package/dist/domain/nativeInvestigationGraph.js +351 -0
  398. package/dist/domain/nativeValueFlow.js +61 -0
  399. package/dist/domain/nodeRuntimeCharacterization.js +15 -18
  400. package/dist/domain/objcSwiftMetadata.js +254 -0
  401. package/dist/domain/peInspection.js +1 -1
  402. package/dist/domain/permissionPolicy.js +13 -0
  403. package/dist/domain/processCapture.js +76 -113
  404. package/dist/domain/processCaptureExample.js +68 -0
  405. package/dist/domain/processCaptureParsing.js +21 -0
  406. package/dist/domain/processCaptureReactiveSchema.js +68 -0
  407. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  408. package/dist/domain/processCaptureValidation.js +8 -10
  409. package/dist/domain/processComparison.js +12 -16
  410. package/dist/domain/processObservation.js +5 -6
  411. package/dist/domain/processReactiveMatching.js +32 -46
  412. package/dist/domain/processReactiveRuntime.js +4 -8
  413. package/dist/domain/processReactiveScenario.js +28 -94
  414. package/dist/domain/processReactiveScenarioPreflight.js +5 -30
  415. package/dist/domain/processReactiveTransition.js +42 -21
  416. package/dist/domain/processScenario.js +62 -93
  417. package/dist/domain/processTraceComparison.js +0 -7
  418. package/dist/domain/processTraceEvaluation.js +14 -4
  419. package/dist/domain/processTraceSpecification.js +11 -17
  420. package/dist/domain/protocolCapture.js +11 -9
  421. package/dist/domain/reconstructionCoverage.js +62 -129
  422. package/dist/domain/reconstructionCoverageEvaluation.js +17 -17
  423. package/dist/domain/reconstructionObligationLedgerSchemas.js +45 -72
  424. package/dist/domain/reconstructionReadiness.js +1 -2
  425. package/dist/domain/reconstructionReadinessSchemas.js +66 -40
  426. package/dist/domain/reconstructionUnknowns.js +3 -3
  427. package/dist/domain/reconstructionVerification.js +13 -47
  428. package/dist/domain/reconstructionVerificationSchemas.js +50 -38
  429. package/dist/domain/referenceSourceGraph.js +53 -61
  430. package/dist/domain/referenceSourceImportParsing.js +3 -7
  431. package/dist/domain/replayMachine.js +19 -31
  432. package/dist/domain/replayMachineRun.js +15 -63
  433. package/dist/domain/replayMachineRuntime.js +46 -44
  434. package/dist/domain/replayMachineValues.js +84 -0
  435. package/dist/domain/residualUnknown.js +25 -30
  436. package/dist/domain/runtimeCharacterization.js +15 -16
  437. package/dist/domain/runtimeIdentification.js +48 -47
  438. package/dist/domain/sourceToBundleComparison.js +11 -87
  439. package/dist/domain/sourceToBundleComparisonSchemas.js +25 -50
  440. package/dist/domain/sourceToBundleSignals.js +11 -16
  441. package/dist/domain/staticRuntimeCorrelation.js +44 -54
  442. package/dist/domain/symbolAnalysis.js +10 -19
  443. package/dist/domain/unicodeCodePointOrder.js +12 -0
  444. package/dist/domain/webBundleAnalysis.js +70 -99
  445. package/dist/domain/webBundleAnalyzer.js +2 -4
  446. package/dist/domain/webBundleAnalyzerAst.js +0 -13
  447. package/dist/domain/webBundleAnalyzerInspection.js +26 -52
  448. package/dist/domain/webBundleAnalyzerResult.js +7 -24
  449. package/dist/domain/webCaptureDiff.js +48 -85
  450. package/dist/domain/webCaptureDiffSchemas.js +86 -0
  451. package/dist/domain/webContentArtifact.js +1 -10
  452. package/dist/domain/webMcpDiscovery.js +3 -14
  453. package/dist/domain/webScreenshot.js +58 -34
  454. package/dist/domain/zipPackageFormat.js +7 -0
  455. package/dist/dotnet/ManagedArtifactInspector.js +17 -50
  456. package/dist/dotnet/ManagedMemberInspector.js +27 -58
  457. package/dist/dotnet/ManagedMemberInspectorCore.js +14 -51
  458. package/dist/dotnet/ManagedMemberInstructionDecoder.js +2 -2
  459. package/dist/dotnet/ManagedMemberRows.js +16 -16
  460. package/dist/dotnet/ManagedMetadataHeaps.js +26 -8
  461. package/dist/dotnet/ManagedMetadataInventory.js +21 -30
  462. package/dist/dotnet/ManagedMetadataInventoryRows.js +57 -63
  463. package/dist/dotnet/ManagedMetadataLayout.js +3 -5
  464. package/dist/dotnet/ManagedMethodBodyReader.js +5 -30
  465. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +19 -49
  466. package/dist/dotnet/ManagedNativeBoundaryInspector.js +13 -42
  467. package/dist/dotnet/ManagedPeReader.js +2 -2
  468. package/dist/dotnet/ManagedStaticProvider.js +13 -71
  469. package/dist/generatedMcpToolCatalog.js +1 -1
  470. package/dist/generatedPackageMetadata.js +1 -1
  471. package/dist/ghidra/GhidraAnalysisProfile.js +3 -8
  472. package/dist/ghidra/GhidraClient.js +5 -13
  473. package/dist/ghidra/GhidraClientStartup.js +1 -1
  474. package/dist/ghidra/GhidraClientWire.js +9 -5
  475. package/dist/ghidra/GhidraDefaults.js +0 -18
  476. package/dist/ghidra/GhidraDiagnostics.js +0 -2
  477. package/dist/ghidra/GhidraDoctor.js +16 -12
  478. package/dist/ghidra/GhidraFunctionValues.js +67 -108
  479. package/dist/ghidra/GhidraInstallation.js +98 -42
  480. package/dist/ghidra/GhidraInventoryValues.js +18 -77
  481. package/dist/ghidra/GhidraLauncher.js +0 -8
  482. package/dist/ghidra/GhidraProvider.js +32 -31
  483. package/dist/ghidra/GhidraProviderCapabilities.js +11 -48
  484. package/dist/ghidra/GhidraRequestQueue.js +6 -30
  485. package/dist/ghidra/GhidraResponseBuffer.js +1 -7
  486. package/dist/ghidra/GhidraSessionValues.js +0 -2
  487. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  488. package/dist/ghidra/GhidraTransport.js +4 -7
  489. package/dist/ghidra/protocol.js +19 -42
  490. package/dist/hopper/BridgeLauncher.js +115 -37
  491. package/dist/hopper/HopperAnalysisProfile.js +3 -5
  492. package/dist/hopper/HopperCleanup.js +11 -9
  493. package/dist/hopper/HopperClient.js +5 -8
  494. package/dist/hopper/HopperProcessDiagnostic.js +2 -2
  495. package/dist/hopper/HopperProvider.js +0 -30
  496. package/dist/hopper/HopperRequestQueue.js +21 -40
  497. package/dist/hopper/HopperResponseStream.js +1 -9
  498. package/dist/hopper/HopperSessionValues.js +3 -2
  499. package/dist/hopper/HopperTargetLease.js +119 -0
  500. package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +24 -31
  501. package/dist/hopper/LinuxPrivateDisplayProbe.js +21 -26
  502. package/dist/hopper/protocol.js +6 -4
  503. package/dist/main/reload.js +1 -9
  504. package/dist/main/shutdown.js +1 -1
  505. package/dist/main/state.js +0 -23
  506. package/dist/main/transport.js +27 -39
  507. package/dist/main.js +17 -15
  508. package/dist/mcpDoctor.js +27 -69
  509. package/dist/native/CommandRunner.js +18 -25
  510. package/dist/native/NativeMacOSProvider.js +13 -38
  511. package/dist/native/NativeMachoInspection.js +1 -1
  512. package/dist/process/BoundedFileBytes.js +17 -0
  513. package/dist/process/ExecFileOutput.js +11 -0
  514. package/dist/process/PendingOperations.js +8 -6
  515. package/dist/process/PrivateRuntimeRoot.js +17 -0
  516. package/dist/process/ProcessOwnership.js +67 -130
  517. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  518. package/dist/process/ProcessOwnershipObservation.js +87 -0
  519. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  520. package/dist/process/ProviderDeadline.js +8 -12
  521. package/dist/process/ProviderProcess.js +7 -28
  522. package/dist/process/WindowsAuthority.js +32 -0
  523. package/dist/reference/ReferenceSourceReader.js +8 -24
  524. package/dist/reference/ReferenceSourceReaderEntries.js +11 -39
  525. package/dist/reference/ReferenceSourceReaderFile.js +13 -31
  526. package/dist/reference/ReferenceSourceReaderPaths.js +3 -18
  527. package/dist/reference/ReferenceSourceReaderValidate.js +3 -6
  528. package/dist/replay/JavaScriptReplayWorker.js +95 -13
  529. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  530. package/dist/replay/LinuxJavaScriptReplayRunner.js +42 -43
  531. package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -19
  532. package/dist/replay/LinuxRuntimeClosure.js +1 -3
  533. package/dist/replay/ReplayOutcome.js +27 -18
  534. package/dist/replay/ReplayProcessLifecycle.js +32 -7
  535. package/dist/replay/ReplaySeccompFile.js +29 -0
  536. package/dist/replay/ReplayWorkerProtocol.js +33 -30
  537. package/dist/replay/SystemJavaScriptReplayHost.js +45 -74
  538. package/dist/server/ProcessCaptureElicitation.js +4 -8
  539. package/dist/server/createServer.js +145 -119
  540. package/dist/server/mcpClientMetadata.js +32 -0
  541. package/dist/server/promptCompletion.js +37 -61
  542. package/dist/server/recordDerivedEvidence.js +1 -1
  543. package/dist/server/registerApplicationTools/characterization.js +10 -21
  544. package/dist/server/registerApplicationTools/compareExportShapes.js +6 -16
  545. package/dist/server/registerApplicationTools/compareSourceToBundle.js +6 -15
  546. package/dist/server/registerApplicationTools/compareVersions.js +6 -16
  547. package/dist/server/registerApplicationTools/controlledReplay.js +8 -15
  548. package/dist/server/registerApplicationTools/coverage.js +7 -78
  549. package/dist/server/registerApplicationTools/helpers.js +1 -13
  550. package/dist/server/registerApplicationTools/obligationLedger.js +4 -8
  551. package/dist/server/registerApplicationTools/traceFeature.js +6 -15
  552. package/dist/server/registerApplicationTools/traceSemantics.js +5 -13
  553. package/dist/server/registerApplicationTools.js +0 -2
  554. package/dist/server/registerArtifactComparisonTool.js +27 -35
  555. package/dist/server/registerBrowserScenarioTool.js +3 -8
  556. package/dist/server/registerBrowserTools.js +36 -81
  557. package/dist/server/registerBundleComparisonTool.js +10 -16
  558. package/dist/server/registerCloseLifecycleTool.js +5 -27
  559. package/dist/server/registerElectronTools.js +29 -65
  560. package/dist/server/registerEnhancedTools.js +118 -127
  561. package/dist/server/registerEvidenceTools.js +19 -30
  562. package/dist/server/registerFunctionComparisonTool.js +35 -34
  563. package/dist/server/registerInvestigationTools/helpers.js +3 -32
  564. package/dist/server/registerInvestigationTools.js +36 -148
  565. package/dist/server/registerJavaScriptRuntimeObservationTools.js +15 -27
  566. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +16 -23
  567. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  568. package/dist/server/registerManagedWorkflowTools/evidence.js +19 -35
  569. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -14
  570. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +4 -14
  571. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +11 -20
  572. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +10 -21
  573. package/dist/server/registerOfficialTools.js +8 -51
  574. package/dist/server/registerProcessComparisonTool.js +43 -38
  575. package/dist/server/registerPrompts.js +19 -17
  576. package/dist/server/registerReplayMachineTool.js +4 -10
  577. package/dist/server/registerSessionRecordTools.js +36 -153
  578. package/dist/server/registerSessionStatusTool.js +18 -96
  579. package/dist/server/registerSessionTools.js +34 -91
  580. package/dist/server/sessionAvailabilityPolicy.js +2 -3
  581. package/dist/server/sessionEvidence.js +9 -15
  582. package/dist/server/sessionToolPolicies.js +1 -13
  583. package/dist/server/toolRegistrationOptions.js +4 -192
  584. package/dist/server/toolResult.js +15 -67
  585. package/dist/serverIdentity.js +0 -20
  586. package/install.sh +1 -1
  587. package/package.json +27 -15
  588. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  589. package/scripts/electron-active-hook.cjs +469 -0
  590. package/scripts/hopper-demo-x11.py +13 -32
  591. package/scripts/rea.mjs +1 -11
  592. package/skills/reverse-engineer-anything/SKILL.md +46 -11
  593. package/skills/reverse-engineer-anything/references/evidence-workflows.md +6 -4
  594. package/skills/reverse-engineer-anything/references/javascript-applications.md +13 -13
  595. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +12 -8
  596. package/dist/application/ApplicationWorkflowEvidenceResolver.js +0 -180
  597. package/dist/application/BoundedJsonFiles.js +0 -86
  598. package/dist/application/CrossVersionInventory.js +0 -128
  599. package/dist/application/CrossVersionInvestigation.js +0 -301
  600. package/dist/application/CrossVersionInvestigationCollections.js +0 -23
  601. package/dist/application/CrossVersionInvestigationEvidence.js +0 -64
  602. package/dist/application/CrossVersionInvestigationReplay.js +0 -170
  603. package/dist/application/DeferredFileAuthorization.js +0 -61
  604. package/dist/application/DoctorProjection.js +0 -43
  605. package/dist/application/EnhancedToolPagination.js +0 -22
  606. package/dist/application/EvidenceReferenceResolver.js +0 -26
  607. package/dist/application/InvestigationWorkspaceStore.js +0 -204
  608. package/dist/application/ProcessPairedExperiment.js +0 -72
  609. package/dist/application/ReconstructionCoverageWorkspaceStore.js +0 -31
  610. package/dist/application/ReconstructionReadinessService.js +0 -48
  611. package/dist/cliInvestigationCommands.js +0 -173
  612. package/dist/domain/boundedCartesianProjection.js +0 -15
  613. package/dist/domain/investigationWorkspace.js +0 -346
  614. package/dist/domain/jsonLimits.js +0 -26
  615. package/dist/domain/knownPageCoverage.js +0 -21
  616. package/dist/domain/processPairedExperiment.js +0 -128
  617. package/dist/server/DynamicToolAvailability.js +0 -70
  618. package/dist/server/LazyToolCatalog.js +0 -134
  619. package/dist/server/hydrateServerTools.js +0 -191
  620. package/dist/server/javascriptApplicationResult.js +0 -106
  621. package/dist/server/permissionFailure.js +0 -12
  622. package/dist/server/registerApplicationTools/readiness.js +0 -55
  623. package/dist/server/registerEvidenceResources.js +0 -315
  624. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -65
  625. package/dist/server/registerReconstructionObligationLedgerResource.js +0 -32
  626. package/dist/server/registerReconstructionReadinessResource.js +0 -32
  627. package/dist/server/toolInputValidation.js +0 -77
  628. package/scripts/package-runner-bootstrap.mjs +0 -72
@@ -9,19 +9,15 @@ import json
9
9
  import hmac
10
10
  import os
11
11
  import re
12
- import sre_parse
13
12
  import socket
14
13
  from typing import Any, Optional, Protocol, Sequence
15
14
 
16
- MAX_LINE_BYTES = 10 * 1024 * 1024
17
- MAX_READ_BYTES = 4096
18
15
  BAD_ADDRESSES = (-1, 0xFFFFFFFFFFFFFFFF, None)
19
16
  _selected_document = None
17
+ _rea_session_document = None
20
18
  _search_inventory_cache = {}
21
19
  _pseudocode_cache = {}
22
20
  _hopper_api = None
23
- MAX_SEARCH_PATTERN_LENGTH = 256
24
- MAX_SEARCH_VALUE_LENGTH = 4096
25
21
 
26
22
 
27
23
  class HopperDocument(Protocol):
@@ -69,8 +65,9 @@ class HopperApiFacade:
69
65
 
70
66
  def _configure_hopper_api(document_provider):
71
67
  """Inject Hopper's document provider or a standalone test facade."""
72
- global _hopper_api
68
+ global _hopper_api, _rea_session_document
73
69
  _hopper_api = HopperApiFacade(document_provider)
70
+ _rea_session_document = None
74
71
 
75
72
 
76
73
  def _api():
@@ -88,19 +85,43 @@ def _api():
88
85
 
89
86
 
90
87
  def _session_document():
91
- """Find only the document opened for this authenticated REA session."""
88
+ """Return the exact document bound to this authenticated REA session."""
89
+ global _rea_session_document
90
+ documents = _api().documents()
91
+ if _rea_session_document is not None:
92
+ return (
93
+ _rea_session_document
94
+ if any(document is _rea_session_document for document in documents)
95
+ else None
96
+ )
97
+ return _bind_session_document(documents)
98
+
99
+
100
+ def _bind_session_document(documents=None):
101
+ """Bind this bridge to Hopper's current document for its target."""
102
+ global _rea_session_document
103
+ api = _api()
104
+ if documents is None:
105
+ documents = api.documents()
92
106
  target = os.path.realpath(REA_TARGET_PATH)
93
- for document in _api().documents():
94
- paths = (document.getExecutableFilePath(), document.getDatabaseFilePath())
95
- for path in paths:
96
- if path and os.path.realpath(path) == target:
97
- return document
98
- return None
99
107
 
108
+ def matches_target(document):
109
+ paths = (document.getExecutableFilePath(), document.getDatabaseFilePath())
110
+ return any(path and os.path.realpath(path) == target for path in paths)
100
111
 
101
- MAX_REGEX_BACKTRACKING_PATHS = 10000
102
- MAX_REGEX_CANDIDATE_LENGTH = 4096
103
- MAX_REGEX_SEARCH_WORK_UNITS = 1000000
112
+ current = api.current_document()
113
+ if current is not None and matches_target(current):
114
+ _rea_session_document = current
115
+ return current
116
+ matching = [document for document in documents if matches_target(document)]
117
+ if len(matching) == 1:
118
+ _rea_session_document = matching[0]
119
+ return matching[0]
120
+ if len(matching) > 1:
121
+ raise CapabilityUnavailableError(
122
+ "The REA session document is ambiguous; Hopper did not identify the launched document"
123
+ )
124
+ return None
104
125
 
105
126
 
106
127
  class CapabilityUnavailableError(Exception):
@@ -149,14 +170,22 @@ def _document(name=None):
149
170
  api = _api()
150
171
  documents = api.documents()
151
172
  if name is not None:
152
- for candidate in documents:
153
- if candidate.getDocumentName() == name:
154
- return candidate
173
+ matches = [candidate for candidate in documents if candidate.getDocumentName() == name]
174
+ if len(matches) == 1:
175
+ return matches[0]
176
+ if len(matches) > 1:
177
+ current = api.current_document()
178
+ if current is not None and current.getDocumentName() == name:
179
+ return current
180
+ raise ValueError("Hopper document name is ambiguous")
155
181
  raise ValueError("Unknown Hopper document")
156
182
  if _selected_document is not None:
157
183
  for candidate in documents:
158
184
  if candidate.getDocumentName() == _selected_document:
159
185
  return candidate
186
+ session_document = _session_document()
187
+ if session_document is not None:
188
+ return session_document
160
189
  current = api.current_document()
161
190
  if current is None:
162
191
  raise ValueError("No Hopper document is loaded")
@@ -225,18 +254,14 @@ def _containing_procedure(document, address):
225
254
  return (procedure, None) if procedure is not None else (None, "not_in_procedure")
226
255
 
227
256
 
228
- def _instruction_addresses(procedure, limit):
257
+ def _instruction_addresses(procedure):
229
258
  result = []
230
259
  seen = set()
231
260
  segment = procedure.getSegment()
232
- truncated = False
233
261
  for block in procedure.basicBlockIterator():
234
262
  address = block.getStartingAddress()
235
263
  end = block.getEndingAddress()
236
264
  while address < end and address not in seen:
237
- if len(result) >= limit:
238
- truncated = True
239
- return result, truncated
240
265
  seen.add(address)
241
266
  instruction = segment.getInstructionAtAddress(address)
242
267
  if instruction is None:
@@ -246,24 +271,15 @@ def _instruction_addresses(procedure, limit):
246
271
  if length <= 0:
247
272
  break
248
273
  address += length
249
- return result, truncated
274
+ return result
250
275
 
251
276
 
252
277
  def _procedure_references(document, params):
253
278
  procedure = _procedure(document, params.get("procedure"))
254
279
  direction = params.get("direction", "outgoing")
255
- offset = params.get("offset", 0)
256
- limit = params.get("limit", 100)
257
- max_instructions = params.get("max_instructions", 500)
258
280
  if direction not in ("incoming", "outgoing"):
259
281
  raise ValueError("direction must be incoming or outgoing")
260
- if not isinstance(offset, int) or isinstance(offset, bool) or offset < 0:
261
- raise ValueError("offset must be a non-negative integer")
262
- if not isinstance(limit, int) or isinstance(limit, bool) or limit < 1 or limit > 500:
263
- raise ValueError("limit must be an integer between 1 and 500")
264
- if not isinstance(max_instructions, int) or isinstance(max_instructions, bool) or max_instructions < 1 or max_instructions > 5000:
265
- raise ValueError("max_instructions must be an integer between 1 and 5000")
266
- addresses, scan_truncated = _instruction_addresses(procedure, max_instructions)
282
+ addresses = _instruction_addresses(procedure)
267
283
  edges = set()
268
284
  for address in addresses:
269
285
  segment = _segment(document, address)
@@ -272,8 +288,7 @@ def _procedure_references(document, params):
272
288
  edges.add((address, reference) if direction == "outgoing" else (reference, address))
273
289
  ordered = sorted(edges)
274
290
  items = []
275
- selected = ordered[offset:offset + limit]
276
- for source, target in selected:
291
+ for source, target in ordered:
277
292
  source_procedure, _ = _containing_procedure(document, source)
278
293
  target_procedure, _ = _containing_procedure(document, target)
279
294
  items.append({
@@ -283,13 +298,9 @@ def _procedure_references(document, params):
283
298
  "target_procedure": _procedure_identity(target_procedure) if target_procedure is not None else None,
284
299
  "kind": _unavailable("Hopper's public Python API does not classify reference kinds"),
285
300
  })
286
- next_offset = offset + len(selected)
287
- has_more = next_offset < len(ordered)
288
- truncated = scan_truncated or has_more
289
301
  return {
290
302
  "procedure": _procedure_identity(procedure), "direction": direction,
291
- "references": {"items": items, "total": None if scan_truncated else len(ordered), "returned": len(items), "truncated": truncated, "next_offset": next_offset if has_more and not scan_truncated else None},
292
- "instructions_scanned": len(addresses), "instruction_scan_truncated": scan_truncated,
303
+ "references": items,
293
304
  }
294
305
 
295
306
 
@@ -352,230 +363,39 @@ def _search_inventory(document, kind):
352
363
  return inventory
353
364
 
354
365
 
355
- def _checked_regex_paths(left, right, operation):
356
- """Apply one path-count operation without crossing the static work budget."""
357
- if operation == "add":
358
- exceeded = left > MAX_REGEX_BACKTRACKING_PATHS - right
359
- result = left + right
360
- else:
361
- exceeded = right != 0 and left > MAX_REGEX_BACKTRACKING_PATHS // right
362
- result = left * right
363
- if exceeded or result > MAX_REGEX_BACKTRACKING_PATHS:
364
- raise ValueError(
365
- "Regex exceeds the %d-path backtracking budget"
366
- % MAX_REGEX_BACKTRACKING_PATHS
367
- )
368
- return result
369
-
370
-
371
- def _repeat_regex_paths(child_paths, minimum, maximum):
372
- """Count every bounded repetition path, including alternative child paths."""
373
- paths = 0
374
- repeated_paths = 1
375
- for count in range(maximum + 1):
376
- if count >= minimum:
377
- paths = _checked_regex_paths(paths, repeated_paths, "add")
378
- if count < maximum:
379
- repeated_paths = _checked_regex_paths(
380
- repeated_paths, child_paths, "multiply"
381
- )
382
- return paths
383
-
384
-
385
- def _validate_regex_class(items):
386
- """Accept only constant-time character-class operations."""
387
- allowed = {
388
- sre_parse.CATEGORY,
389
- sre_parse.LITERAL,
390
- sre_parse.NEGATE,
391
- sre_parse.RANGE,
392
- }
393
- if any(operation not in allowed for operation, _ in items):
394
- raise ValueError("Regex operation is not supported by the bounded matcher")
395
-
396
-
397
- def _validate_regex_node(node, inside_repeat=False):
398
- """Return capped path and step bounds for Python regex evaluation."""
399
- leaf_operations = {
400
- sre_parse.ANY,
401
- sre_parse.AT,
402
- sre_parse.CATEGORY,
403
- sre_parse.LITERAL,
404
- sre_parse.NOT_LITERAL,
405
- }
406
- forbidden = {
407
- sre_parse.ASSERT,
408
- sre_parse.ASSERT_NOT,
409
- sre_parse.GROUPREF,
410
- sre_parse.GROUPREF_EXISTS,
411
- }
412
- for name in ("GROUPREF_IGNORE", "GROUPREF_LOC_IGNORE", "GROUPREF_UNI_IGNORE"):
413
- operation = getattr(sre_parse, name, None)
414
- if operation is not None:
415
- forbidden.add(operation)
416
- repeat_tokens = {sre_parse.MAX_REPEAT, sre_parse.MIN_REPEAT}
417
- possessive = getattr(sre_parse, "POSSESSIVE_REPEAT", None)
418
- if possessive is not None:
419
- repeat_tokens.add(possessive)
420
- atomic = getattr(sre_parse, "ATOMIC_GROUP", None)
421
-
422
- paths = 1
423
- steps = 0
424
- for operation, argument in node:
425
- if operation in forbidden:
426
- raise ValueError("Regex lookarounds and backreferences are not supported")
427
- if operation in leaf_operations:
428
- operation_paths = 1
429
- operation_steps = 1
430
- elif operation == sre_parse.IN:
431
- _validate_regex_class(argument)
432
- operation_paths = 1
433
- operation_steps = 1
434
- elif operation in repeat_tokens:
435
- if inside_repeat:
436
- raise ValueError("Nested regex repetitions are not supported")
437
- minimum, maximum, child = argument
438
- if maximum == sre_parse.MAXREPEAT or maximum > 1000:
439
- raise ValueError(
440
- "Unbounded or excessive regex repetitions are not supported"
441
- )
442
- child_paths, child_steps = _validate_regex_node(child, True)
443
- operation_paths = _repeat_regex_paths(
444
- child_paths, minimum, maximum
445
- )
446
- operation_steps = maximum * child_steps
447
- elif operation == sre_parse.SUBPATTERN:
448
- operation_paths, operation_steps = _validate_regex_node(
449
- argument[-1], inside_repeat
450
- )
451
- elif operation == sre_parse.BRANCH:
452
- operation_paths = 0
453
- operation_steps = 0
454
- for branch in argument[1]:
455
- branch_paths, branch_steps = _validate_regex_node(
456
- branch, inside_repeat
457
- )
458
- operation_paths = _checked_regex_paths(
459
- operation_paths,
460
- branch_paths,
461
- "add",
462
- )
463
- operation_steps = max(operation_steps, branch_steps)
464
- elif atomic is not None and operation == atomic:
465
- operation_paths, operation_steps = _validate_regex_node(
466
- argument, inside_repeat
467
- )
468
- else:
469
- raise ValueError("Regex operation is not supported by the bounded matcher")
470
- paths = _checked_regex_paths(paths, operation_paths, "multiply")
471
- steps += operation_steps
472
- return paths, steps
473
-
474
-
475
- def _bounded_regex_matcher(expression, backtracking_paths, steps_per_path):
476
- """Create a matcher with per-candidate and cumulative work bounds."""
477
- remaining_work = MAX_REGEX_SEARCH_WORK_UNITS
478
- work_per_character = backtracking_paths * max(steps_per_path, 1)
479
-
480
- def matches(value):
481
- nonlocal remaining_work
482
- if not isinstance(value, str):
483
- raise ValueError("Regex candidates must be strings")
484
- if len(value) > MAX_REGEX_CANDIDATE_LENGTH:
485
- raise ValueError(
486
- "Regex candidate exceeds the %d-character safety limit"
487
- % MAX_REGEX_CANDIDATE_LENGTH
488
- )
489
- required_work = work_per_character * max(len(value), 1)
490
- if required_work > remaining_work:
491
- raise ValueError(
492
- "Regex search exceeds the %d-unit work budget"
493
- % MAX_REGEX_SEARCH_WORK_UNITS
494
- )
495
- remaining_work -= required_work
496
- return expression.search(value) is not None
497
-
498
- return matches
499
-
500
-
501
- def _search_page(document, kind, params):
366
+ def _search_results(document, kind, params):
502
367
  pattern = params.get("pattern")
503
- if not isinstance(pattern, str) or not pattern or len(pattern) > MAX_SEARCH_PATTERN_LENGTH:
504
- raise ValueError("pattern must contain between 1 and 256 characters")
368
+ if not isinstance(pattern, str) or not pattern:
369
+ raise ValueError("pattern must be a non-empty string")
505
370
  mode = params.get("mode", "literal")
506
371
  if mode not in ("literal", "regex"):
507
372
  raise ValueError("mode must be literal or regex")
508
373
  case_sensitive = params.get("case_sensitive", False)
509
374
  if not isinstance(case_sensitive, bool):
510
375
  raise ValueError("case_sensitive must be a boolean")
511
- offset = params.get("offset", 0)
512
- limit = params.get("limit", 100)
513
- if not isinstance(offset, int) or isinstance(offset, bool) or offset < 0:
514
- raise ValueError("offset must be a non-negative integer")
515
- if not isinstance(limit, int) or isinstance(limit, bool) or limit < 1 or limit > 100:
516
- raise ValueError("limit must be an integer between 1 and 100")
517
376
 
518
377
  if mode == "literal":
519
378
  needle = pattern if case_sensitive else pattern.casefold()
520
379
  matches = lambda value: needle in (value if case_sensitive else value.casefold())
521
380
  else:
522
381
  try:
523
- parsed = sre_parse.parse(pattern)
524
- backtracking_paths, steps_per_path = _validate_regex_node(parsed)
525
382
  expression = re.compile(pattern, 0 if case_sensitive else re.IGNORECASE)
526
383
  except (re.error, OverflowError) as error:
527
384
  raise ValueError("Invalid regex pattern") from error
528
- matches = _bounded_regex_matcher(
529
- expression, backtracking_paths, steps_per_path
530
- )
385
+ matches = lambda value: expression.search(value) is not None
531
386
 
532
387
  selected = []
533
- total = 0
534
- page_end = offset + limit
535
388
  for item in _search_inventory(document, kind):
536
389
  if not matches(item[1]):
537
390
  continue
538
- if offset <= total < page_end:
539
- selected.append(item)
540
- total += 1
541
- next_offset = offset + len(selected)
542
- has_more = next_offset < total
543
- return {
544
- "items": [
391
+ selected.append(item)
392
+ return [
545
393
  {
546
394
  "address": address,
547
- "value": value[:MAX_SEARCH_VALUE_LENGTH],
548
- "value_truncated": len(value) > MAX_SEARCH_VALUE_LENGTH,
395
+ "value": value,
549
396
  }
550
397
  for address, value in selected
551
- ],
552
- "offset": offset,
553
- "limit": limit,
554
- "total": total,
555
- "next_offset": next_offset if has_more else None,
556
- "has_more": has_more,
557
- }
558
-
559
-
560
- def _page(values, offset, limit):
561
- """Return one deterministically address-sorted page without crossing an unbounded map."""
562
- if not isinstance(offset, int) or isinstance(offset, bool) or offset < 0:
563
- raise ValueError("offset must be a non-negative integer")
564
- if not isinstance(limit, int) or isinstance(limit, bool) or limit < 1 or limit > 500:
565
- raise ValueError("limit must be an integer between 1 and 500")
566
- ordered = sorted(values.items(), key=lambda item: int(item[0], 16))
567
- selected = ordered[offset:offset + limit]
568
- total = len(ordered)
569
- next_offset = offset + len(selected)
570
- has_more = next_offset < total
571
- return {
572
- "items": [{"address": address, "value": value} for address, value in selected],
573
- "offset": offset,
574
- "limit": limit,
575
- "total": total,
576
- "next_offset": next_offset if has_more else None,
577
- "has_more": has_more,
578
- }
398
+ ]
579
399
 
580
400
 
581
401
  def _unavailable(reason):
@@ -583,36 +403,6 @@ def _unavailable(reason):
583
403
  return {"available": False, "reason": reason}
584
404
 
585
405
 
586
- def _offset(params, name):
587
- value = params.get(name, 0)
588
- if not isinstance(value, int) or isinstance(value, bool) or value < 0:
589
- raise ValueError("%s must be a non-negative integer" % name)
590
- return value
591
-
592
-
593
- def _collection_offset(params, name):
594
- values = params.get("collection_offset", {})
595
- if not isinstance(values, dict):
596
- raise ValueError("collection_offset must be an object")
597
- value = values.get(name, 0)
598
- if not isinstance(value, int) or isinstance(value, bool) or value < 0:
599
- raise ValueError("collection_offset.%s must be a non-negative integer" % name)
600
- return value
601
-
602
-
603
- def _bounded(items, offset, limit, total=None, scan_truncated=False):
604
- selected = items[offset:offset + limit]
605
- known_total = len(items) if total is None and not scan_truncated else total
606
- has_more = offset + len(selected) < len(items)
607
- return {
608
- "items": selected,
609
- "total": known_total,
610
- "returned": len(selected),
611
- "truncated": scan_truncated or has_more,
612
- "next_offset": offset + len(selected) if has_more else None,
613
- }
614
-
615
-
616
406
  def _name_map(document):
617
407
  result = {}
618
408
  for segment in document.getSegmentsList():
@@ -639,8 +429,8 @@ def _render_instruction(segment, address):
639
429
  )
640
430
 
641
431
 
642
- def _assembly(procedure, limit=None):
643
- """Render bounded assembly while guarding against malformed instruction cycles."""
432
+ def _assembly(procedure):
433
+ """Render assembly while guarding against malformed instruction cycles."""
644
434
  lines = []
645
435
  segment = procedure.getSegment()
646
436
  seen = set()
@@ -655,8 +445,6 @@ def _assembly(procedure, limit=None):
655
445
  line = _render_instruction(segment, address)
656
446
  if line is not None:
657
447
  lines.append(line)
658
- if limit is not None and len(lines) >= limit:
659
- return "\n".join(lines)
660
448
  length = instruction.getInstructionLength()
661
449
  if length <= 0:
662
450
  break
@@ -665,37 +453,18 @@ def _assembly(procedure, limit=None):
665
453
 
666
454
 
667
455
  def _read_function_instructions(document, params):
668
- """Read one bounded raw-instruction window without invoking decompilation."""
456
+ """Read all raw instructions without invoking decompilation."""
669
457
  procedure = _procedure(document, params.get("procedure"))
670
- offset = _offset(params, "offset")
671
- limit = params.get("limit", 64)
672
- if offset > 100000:
673
- raise ValueError("offset must not exceed 100000")
674
- if not isinstance(limit, int) or isinstance(limit, bool) or limit < 1 or limit > 500:
675
- raise ValueError("limit must be an integer between 1 and 500")
676
- addresses, scan_truncated = _instruction_addresses(
677
- procedure, offset + limit + 1
678
- )
679
- start = min(offset, len(addresses))
680
- end = min(len(addresses), start + limit)
458
+ addresses = _instruction_addresses(procedure)
681
459
  segment = procedure.getSegment()
682
460
  items = []
683
- for address in addresses[start:end]:
461
+ for address in addresses:
684
462
  line = _render_instruction(segment, address)
685
463
  if line is not None:
686
464
  items.append(line)
687
- has_more = scan_truncated or end < len(addresses)
688
465
  return {
689
466
  "procedure": _procedure_identity(procedure),
690
- "instructions": {
691
- "items": items,
692
- "total": None if scan_truncated else len(addresses),
693
- "returned": len(items),
694
- "truncated": has_more,
695
- "next_offset": end if has_more else None,
696
- },
697
- "instructions_scanned": len(addresses),
698
- "instruction_scan_truncated": scan_truncated,
467
+ "instructions": items,
699
468
  "limitations": [
700
469
  "Instruction text and ordering are Hopper-specific representations.",
701
470
  "The fast path does not decompile the procedure or scan whole-program names and strings.",
@@ -704,20 +473,9 @@ def _read_function_instructions(document, params):
704
473
 
705
474
 
706
475
  def _analyze_function(document, params):
707
- """Collect a bounded, single-pass function dossier for agent callers."""
476
+ """Collect the complete function dossier for agent callers."""
708
477
  procedure = _procedure(document, params.get("procedure"))
709
- limit = params.get("limit", 100)
710
- max_chars = params.get("max_pseudocode_chars", 20000)
711
- max_instructions = params.get("max_instructions", 500)
712
- pseudocode_offset = _offset(params, "pseudocode_offset")
713
- assembly_offset = _offset(params, "assembly_offset")
714
- if not isinstance(limit, int) or isinstance(limit, bool) or limit < 1 or limit > 500:
715
- raise ValueError("limit must be an integer between 1 and 500")
716
- if not isinstance(max_chars, int) or isinstance(max_chars, bool) or max_chars < 1 or max_chars > 100000:
717
- raise ValueError("max_pseudocode_chars must be between 1 and 100000")
718
- if not isinstance(max_instructions, int) or isinstance(max_instructions, bool) or max_instructions < 1 or max_instructions > 5000:
719
- raise ValueError("max_instructions must be between 1 and 5000")
720
- addresses, instruction_scan_truncated = _instruction_addresses(procedure, max_instructions)
478
+ addresses = _instruction_addresses(procedure)
721
479
  blocks = []
722
480
  all_blocks = list(procedure.basicBlockIterator())
723
481
  for block in all_blocks:
@@ -732,7 +490,7 @@ def _analyze_function(document, params):
732
490
  "successors": sorted(set(successors), key=lambda value: int(value, 16)),
733
491
  })
734
492
  pseudo = _pseudocode(document, procedure) or ""
735
- assembly_lines = _assembly(procedure, max_instructions).splitlines() if params.get("include_assembly", False) else []
493
+ assembly_lines = _assembly(procedure).splitlines()
736
494
  callers = sorted((_procedure_identity(item) for item in procedure.getAllCallerProcedures()), key=lambda item: int(item["address"], 16))
737
495
  callees = sorted((_procedure_identity(item) for item in procedure.getAllCalleeProcedures()), key=lambda item: int(item["address"], 16))
738
496
  comments = []
@@ -785,28 +543,17 @@ def _analyze_function(document, params):
785
543
  comments.sort(key=lambda item: (int(item["address"], 16), item["kind"]))
786
544
  referenced_strings.sort(key=lambda item: (int(item["address"], 16), int(item["source_address"], 16)))
787
545
  referenced_names.sort(key=lambda item: (int(item["address"], 16), int(item["source_address"], 16)))
788
- pseudo_text = pseudo[pseudocode_offset:pseudocode_offset + max_chars]
789
- pseudo_next = pseudocode_offset + len(pseudo_text)
790
- def collection(name, items, scan_limited=False):
791
- return _bounded(items, _collection_offset(params, name), limit, None, scan_limited)
792
546
  return {
793
547
  "procedure": {"address": _hex(procedure.getEntryPoint()), "name": _procedure_name(procedure), "classification": None, "signature": procedure.signatureString(), "locals": _procedure_locals(procedure)},
794
- "pseudocode": {"text": pseudo_text, "total_chars": len(pseudo), "returned_chars": len(pseudo_text), "truncated": pseudo_next < len(pseudo), "next_offset": pseudo_next if pseudo_next < len(pseudo) else None},
795
- "assembly": _bounded(
796
- assembly_lines,
797
- assembly_offset,
798
- max_instructions,
799
- None,
800
- instruction_scan_truncated if params.get("include_assembly", False) else False,
801
- ),
802
- "comments": collection("comments", comments, instruction_scan_truncated),
803
- "callers": collection("callers", callers), "callees": collection("callees", callees),
804
- "incoming_references": collection("incoming_references", incoming, instruction_scan_truncated),
805
- "outgoing_references": collection("outgoing_references", outgoing, instruction_scan_truncated),
806
- "referenced_strings": collection("referenced_strings", referenced_strings, instruction_scan_truncated),
807
- "referenced_names": collection("referenced_names", referenced_names, instruction_scan_truncated),
808
- "basic_blocks": collection("basic_blocks", blocks),
809
- "instruction_scan": {"scanned": len(addresses), "truncated": instruction_scan_truncated},
548
+ "pseudocode": pseudo,
549
+ "assembly": assembly_lines,
550
+ "comments": comments,
551
+ "callers": callers, "callees": callees,
552
+ "incoming_references": incoming,
553
+ "outgoing_references": outgoing,
554
+ "referenced_strings": referenced_strings,
555
+ "referenced_names": referenced_names,
556
+ "basic_blocks": blocks,
810
557
  "limitations": [
811
558
  "Hopper's public Python API does not classify reference kinds.",
812
559
  "Hopper's public Python API does not expose equivalent external or thunk classification in this dossier.",
@@ -825,6 +572,13 @@ def _dispatch(method, params):
825
572
  document = _session_document()
826
573
  if document is None:
827
574
  return {"shutdown": True, "analysis_stopped": True, "document_closed": True}
575
+ if method == "shutdown" and not REA_OWNS_PROCESS_LIFETIME:
576
+ return {
577
+ "shutdown": True,
578
+ "analysis_stopped": not document.backgroundProcessActive(),
579
+ "document_closed": False,
580
+ "document_retained": True,
581
+ }
828
582
  if document.backgroundProcessActive():
829
583
  document.requestBackgroundProcessStop()
830
584
  if method == "shutdown" and REA_OWNS_PROCESS_LIFETIME:
@@ -865,8 +619,8 @@ def _dispatch(method, params):
865
619
  length = params.get("length", 256)
866
620
  if isinstance(length, bool) or not isinstance(length, int):
867
621
  raise ValueError("Byte-read length must be an integer")
868
- if length < 1 or length > MAX_READ_BYTES:
869
- raise ValueError("Byte-read length must be between 1 and 4096")
622
+ if length < 1:
623
+ raise ValueError("Byte-read length must be at least 1")
870
624
  reader = getattr(document, "readBytes", None)
871
625
  if not callable(reader):
872
626
  raise CapabilityUnavailableError(
@@ -968,24 +722,24 @@ def _dispatch(method, params):
968
722
  })
969
723
  return result
970
724
  if method == "list_procedures":
971
- return _page(dict(_search_inventory(document, "procedure")), params.get("offset", 0), params.get("limit", 100))
725
+ return [{"address": address, "value": value} for address, value in _search_inventory(document, "procedure")]
972
726
  if method == "list_strings":
973
727
  values = dict(_search_inventory(document, "string"))
974
728
  requested = params.get("address")
975
729
  if requested is not None:
976
730
  key = _hex(_address(document, requested))
977
731
  values = {key: values[key]} if key in values else {}
978
- return _page(values, params.get("offset", 0), params.get("limit", 100))
732
+ return [{"address": _hex(address), "value": value} for address, value in sorted(values.items())]
979
733
  if method == "list_names":
980
734
  result = dict(_search_inventory(document, "name"))
981
735
  requested = params.get("address")
982
736
  if requested is not None:
983
737
  key = _hex(_address(document, requested))
984
738
  result = {key: result[key]} if key in result else {}
985
- return _page(result, params.get("offset", 0), params.get("limit", 100))
739
+ return [{"address": _hex(address), "value": value} for address, value in sorted(result.items(), key=lambda item: int(item[0]))]
986
740
  if method in ("search_procedures", "search_strings"):
987
741
  kind = "procedure" if method == "search_procedures" else "string"
988
- return _search_page(document, kind, params)
742
+ return _search_results(document, kind, params)
989
743
  if method.startswith("procedure_"):
990
744
  procedure = _procedure(document, params.get("procedure"))
991
745
  if method == "procedure_address":
@@ -1039,11 +793,11 @@ def _dispatch(method, params):
1039
793
 
1040
794
 
1041
795
  def _serve_connection(connection):
1042
- """Serve one size-bounded, capability-authenticated NDJSON connection."""
796
+ """Serve one capability-authenticated NDJSON connection."""
1043
797
  file = connection.makefile("rwb")
1044
798
  while True:
1045
- line = file.readline(MAX_LINE_BYTES + 1)
1046
- if not line or len(line) > MAX_LINE_BYTES:
799
+ line = file.readline()
800
+ if not line:
1047
801
  break
1048
802
  request_id = None
1049
803
  authenticated = False
@@ -1119,13 +873,13 @@ def _safe_diagnostic(error):
1119
873
  """Project one exception without retaining provider or credential text."""
1120
874
  diagnostic_type = _diagnostic_type(error)
1121
875
  if diagnostic_type == "capability_unavailable":
1122
- message = str(error)[:512]
876
+ message = str(error)
1123
877
  elif diagnostic_type == "authorization":
1124
878
  message = "Invalid bridge capability"
1125
879
  elif diagnostic_type == "invalid_request":
1126
880
  message = "Invalid Hopper bridge request"
1127
881
  else:
1128
- message = "%s: Hopper bridge operation failed" % type(error).__name__[:128]
882
+ message = "%s: Hopper bridge operation failed" % type(error).__name__
1129
883
  return {"code": -32000, "message": message, "type": diagnostic_type}
1130
884
 
1131
885
 
@@ -1147,6 +901,7 @@ def _run():
1147
901
 
1148
902
 
1149
903
  # Hopper's public objects are bound to its dedicated Python execution thread.
1150
- # Keep dispatch on that thread; moving calls to an arbitrary worker can deadlock.
904
+ # Keep dispatch on that thread; moving calls to a worker can deadlock.
1151
905
  if __name__ == "__main__":
906
+ _bind_session_document()
1152
907
  _run()