@eyeauras/insight-cli 0.2.0 → 0.2.1

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 (384) hide show
  1. package/.cli-package-build.json +1 -1
  2. package/README.md +25 -0
  3. package/SKILL.md +38 -54
  4. package/dist/src/binary.d.ts +3 -0
  5. package/dist/src/binary.js +74 -0
  6. package/dist/src/capture.d.ts +3 -0
  7. package/dist/src/capture.js +220 -0
  8. package/dist/src/cli.js +57 -12
  9. package/dist/src/contexts.d.ts +5 -0
  10. package/dist/src/contexts.js +42 -16
  11. package/dist/src/debugger-caller.d.ts +17 -0
  12. package/dist/src/debugger-caller.js +129 -0
  13. package/dist/src/debugger-launch.d.ts +2 -0
  14. package/dist/src/debugger-launch.js +17 -0
  15. package/dist/src/debugger-results.d.ts +1 -0
  16. package/dist/src/debugger-results.js +8 -0
  17. package/dist/src/debugger-supervisor.js +56 -13
  18. package/dist/src/debugger.js +16 -7
  19. package/dist/src/die.d.ts +12 -0
  20. package/dist/src/die.js +127 -0
  21. package/dist/src/dnspy-runtime.d.ts +8 -0
  22. package/dist/src/dnspy-runtime.js +46 -0
  23. package/dist/src/dnspy.d.ts +22 -0
  24. package/dist/src/dnspy.js +160 -0
  25. package/dist/src/dotnet-diagnostics.d.ts +13 -0
  26. package/dist/src/dotnet-diagnostics.js +101 -0
  27. package/dist/src/frida-worker.d.ts +1 -0
  28. package/dist/src/frida-worker.js +125 -0
  29. package/dist/src/frida.d.ts +16 -0
  30. package/dist/src/frida.js +125 -0
  31. package/dist/src/ghidra-debugger-runtime.d.ts +7 -0
  32. package/dist/src/ghidra-debugger-runtime.js +31 -0
  33. package/dist/src/ghidra-processes.d.ts +6 -0
  34. package/dist/src/ghidra-processes.js +121 -0
  35. package/dist/src/ghidra.js +6 -6
  36. package/dist/src/ilspy.d.ts +7 -0
  37. package/dist/src/ilspy.js +122 -0
  38. package/dist/src/lldb.d.ts +10 -0
  39. package/dist/src/lldb.js +99 -0
  40. package/dist/src/llvm.d.ts +6 -0
  41. package/dist/src/llvm.js +133 -0
  42. package/dist/src/managed-heap.d.ts +4 -0
  43. package/dist/src/managed-heap.js +73 -0
  44. package/dist/src/managed-metadata.d.ts +11 -0
  45. package/dist/src/managed-metadata.js +66 -0
  46. package/dist/src/mitmproxy.d.ts +55 -0
  47. package/dist/src/mitmproxy.js +172 -0
  48. package/dist/src/native-inputs.d.ts +3 -2
  49. package/dist/src/native-inputs.js +9 -4
  50. package/dist/src/package-version.d.ts +1 -0
  51. package/dist/src/package-version.js +3 -0
  52. package/dist/src/procmon-config.d.ts +2 -0
  53. package/dist/src/procmon-config.js +15 -0
  54. package/dist/src/procmon-events.d.ts +13 -0
  55. package/dist/src/procmon-events.js +82 -0
  56. package/dist/src/procmon.d.ts +4 -0
  57. package/dist/src/procmon.js +107 -0
  58. package/dist/src/research.d.ts +11 -2
  59. package/dist/src/research.js +5 -3
  60. package/dist/src/runtime-catalog.d.ts +5 -10
  61. package/dist/src/runtime-catalog.js +4 -5
  62. package/dist/src/runtime-manager.d.ts +27 -3
  63. package/dist/src/runtime-manager.js +100 -159
  64. package/dist/src/runtime-selection.js +21 -4
  65. package/dist/src/server.d.ts +13 -0
  66. package/dist/src/server.js +21 -45
  67. package/dist/src/sevenzip.d.ts +15 -0
  68. package/dist/src/sevenzip.js +119 -0
  69. package/dist/src/strace.d.ts +10 -0
  70. package/dist/src/strace.js +71 -0
  71. package/dist/src/text-window.d.ts +11 -0
  72. package/dist/src/text-window.js +6 -0
  73. package/dist/src/tool-runtime/archives.d.ts +10 -0
  74. package/dist/src/{runtime-archives.js → tool-runtime/archives.js} +91 -24
  75. package/dist/src/tool-runtime/catalog.d.ts +3 -0
  76. package/dist/src/tool-runtime/catalog.js +13 -0
  77. package/dist/src/tool-runtime/commands.d.ts +9 -0
  78. package/dist/src/tool-runtime/commands.js +39 -0
  79. package/dist/src/tool-runtime/deadline.d.ts +11 -0
  80. package/dist/src/tool-runtime/deadline.js +32 -0
  81. package/dist/src/tool-runtime/definition.d.ts +73 -0
  82. package/dist/src/tool-runtime/definition.js +49 -0
  83. package/dist/src/tool-runtime/dotnet.d.ts +4 -0
  84. package/dist/src/tool-runtime/dotnet.js +22 -0
  85. package/dist/src/tool-runtime/identity.d.ts +6 -0
  86. package/dist/src/tool-runtime/identity.js +50 -0
  87. package/dist/src/tool-runtime/installer.d.ts +101 -0
  88. package/dist/src/tool-runtime/installer.js +180 -0
  89. package/dist/src/tool-runtime/launch-worker.d.ts +1 -0
  90. package/dist/src/tool-runtime/launch-worker.js +58 -0
  91. package/dist/src/tool-runtime/run.d.ts +51 -0
  92. package/dist/src/tool-runtime/run.js +159 -0
  93. package/dist/src/tool-runtime/store.d.ts +15 -0
  94. package/dist/src/tool-runtime/store.js +219 -0
  95. package/dist/src/tool-runtime/supervisor.d.ts +57 -0
  96. package/dist/src/tool-runtime/supervisor.js +266 -0
  97. package/dist/src/tool-runtime/windows-job.d.ts +22 -0
  98. package/dist/src/tool-runtime/windows-job.js +43 -0
  99. package/dist/src/toolbox.d.ts +84 -0
  100. package/dist/src/toolbox.js +35 -0
  101. package/dist/src/tshark.d.ts +23 -0
  102. package/dist/src/tshark.js +174 -0
  103. package/dist/src/windbg.d.ts +14 -0
  104. package/dist/src/windbg.js +119 -0
  105. package/dist/src/workspace.d.ts +1 -0
  106. package/dist/src/workspace.js +6 -0
  107. package/package.json +5 -4
  108. package/references/agent-execution.md +36 -0
  109. package/references/agent-setup.md +61 -0
  110. package/references/artifacts.md +5 -0
  111. package/references/debugger.md +22 -0
  112. package/references/ilspy.md +33 -0
  113. package/references/managed-runtime.md +48 -7
  114. package/references/native/InsightPythonWheels.java +283 -2
  115. package/references/native/InsightTraceState.java +28 -13
  116. package/references/setup.md +2 -1
  117. package/runtime/managed/insight-heap/Azure.Core.dll +0 -0
  118. package/runtime/managed/insight-heap/Azure.Identity.dll +0 -0
  119. package/runtime/managed/insight-heap/Insight.Heap.csproj +1 -0
  120. package/runtime/managed/insight-heap/Insight.Heap.deps.json +391 -0
  121. package/runtime/managed/insight-heap/Insight.Heap.dll +0 -0
  122. package/runtime/managed/insight-heap/Insight.Heap.runtimeconfig.json +13 -0
  123. package/runtime/managed/insight-heap/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
  124. package/runtime/managed/insight-heap/Microsoft.Diagnostics.NETCore.Client.dll +0 -0
  125. package/runtime/managed/insight-heap/Microsoft.Diagnostics.Runtime.dll +0 -0
  126. package/runtime/managed/insight-heap/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
  127. package/runtime/managed/insight-heap/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
  128. package/runtime/managed/insight-heap/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
  129. package/runtime/managed/insight-heap/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
  130. package/runtime/managed/insight-heap/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
  131. package/runtime/managed/insight-heap/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
  132. package/runtime/managed/insight-heap/Microsoft.Extensions.Options.dll +0 -0
  133. package/runtime/managed/insight-heap/Microsoft.Extensions.Primitives.dll +0 -0
  134. package/runtime/managed/insight-heap/Microsoft.Identity.Client.Extensions.Msal.dll +0 -0
  135. package/runtime/managed/insight-heap/Microsoft.Identity.Client.dll +0 -0
  136. package/runtime/managed/insight-heap/Microsoft.IdentityModel.Abstractions.dll +0 -0
  137. package/runtime/managed/insight-heap/Microsoft.Security.AntiSSRF.dll +0 -0
  138. package/runtime/managed/insight-heap/NuGet.Config +1 -0
  139. package/runtime/managed/insight-heap/Program.cs +20 -0
  140. package/runtime/managed/insight-heap/README.md +16 -0
  141. package/runtime/managed/insight-heap/System.ClientModel.dll +0 -0
  142. package/runtime/managed/insight-heap/System.Memory.Data.dll +0 -0
  143. package/runtime/managed/insight-heap/System.Security.Cryptography.ProtectedData.dll +0 -0
  144. package/runtime/managed/insight-heap/dependencies.json +436 -0
  145. package/runtime/managed/insight-heap/notices/Azure.Core-LICENSE.txt +21 -0
  146. package/runtime/managed/insight-heap/notices/Azure.Identity-LICENSE.txt +21 -0
  147. package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-LICENSE.txt +23 -0
  148. package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-THIRD-PARTY-NOTICES.TXT +1418 -0
  149. package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.NETCore.Client-LICENSE.txt +23 -0
  150. package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.Runtime-LICENSE.txt +23 -0
  151. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-LICENSE.txt +23 -0
  152. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  153. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-LICENSE.txt +23 -0
  154. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  155. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-LICENSE.txt +23 -0
  156. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  157. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-LICENSE.txt +23 -0
  158. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  159. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-LICENSE.txt +23 -0
  160. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  161. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-LICENSE.txt +23 -0
  162. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  163. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-LICENSE.txt +23 -0
  164. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-THIRD-PARTY-NOTICES.TXT +1418 -0
  165. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-LICENSE.txt +23 -0
  166. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-THIRD-PARTY-NOTICES.TXT +1418 -0
  167. package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client-LICENSE.txt +21 -0
  168. package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client.Extensions.Msal-LICENSE.txt +21 -0
  169. package/runtime/managed/insight-heap/notices/Microsoft.IdentityModel.Abstractions-LICENSE.txt +21 -0
  170. package/runtime/managed/insight-heap/notices/Microsoft.Security.AntiSSRF-LICENSE.txt +21 -0
  171. package/runtime/managed/insight-heap/notices/System.ClientModel-LICENSE.txt +21 -0
  172. package/runtime/managed/insight-heap/notices/System.Memory.Data-LICENSE.txt +23 -0
  173. package/runtime/managed/insight-heap/notices/System.Memory.Data-THIRD-PARTY-NOTICES.TXT +1418 -0
  174. package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-LICENSE.TXT +23 -0
  175. package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-THIRD-PARTY-NOTICES.TXT +309 -0
  176. package/runtime/managed/insight-heap/packages.lock.json +165 -0
  177. package/runtime/managed/insight-heap/provenance.json +146 -0
  178. package/runtime/managed/insight-heap/runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll +0 -0
  179. package/runtime/managed/insight-managed/Insight.Managed.csproj +4 -0
  180. package/runtime/managed/insight-managed/Insight.Managed.deps.json +41 -0
  181. package/runtime/managed/insight-managed/Insight.Managed.dll +0 -0
  182. package/runtime/managed/insight-managed/Insight.Managed.runtimeconfig.json +13 -0
  183. package/runtime/managed/insight-managed/LICENSE.dnlib.txt +20 -0
  184. package/runtime/managed/insight-managed/NuGet.Config +1 -0
  185. package/runtime/managed/insight-managed/Program.cs +31 -0
  186. package/runtime/managed/insight-managed/README.md +16 -0
  187. package/runtime/managed/insight-managed/dnlib.dll +0 -0
  188. package/runtime/managed/insight-managed/packages.lock.json +13 -0
  189. package/runtime/managed/insight-managed/provenance.json +40 -0
  190. package/runtime/native/binary/README.md +22 -0
  191. package/runtime/native/binary/dependencies.json +166 -0
  192. package/runtime/native/binary/helper.cpp +44 -0
  193. package/runtime/native/binary/insight-binary-darwin-arm64 +0 -0
  194. package/runtime/native/binary/notices/Catch2-3.12.0--Catch2-3.12.0__LICENSE.txt +23 -0
  195. package/runtime/native/binary/notices/LIEF-LICENSE.txt +202 -0
  196. package/runtime/native/binary/notices/LIEF-attribution.txt +37 -0
  197. package/runtime/native/binary/notices/Melkor_ELF_Fuzzer-ac2495b--elf_fuzzer-master__LICENSE.txt +674 -0
  198. package/runtime/native/binary/notices/expected-1.3.1--expected-1.3.1__COPYING +121 -0
  199. package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__AUTHORS +3 -0
  200. package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__LICENSE +202 -0
  201. package/runtime/native/binary/notices/json-LICENSE.MIT +21 -0
  202. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--LICENSE +553 -0
  203. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--framework__LICENSE +553 -0
  204. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__LICENSE +552 -0
  205. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__framework__LICENSE +553 -0
  206. package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--LICENSE +26 -0
  207. package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--ext__robin_map__LICENSE +21 -0
  208. package/runtime/native/binary/notices/span-LICENSE_1_0.txt +23 -0
  209. package/runtime/native/binary/notices/span-attribution.txt +11 -0
  210. package/runtime/native/binary/notices/spdlog-1.17.0--spdlog-1.17.0__LICENSE +25 -0
  211. package/runtime/native/binary/notices/utfcpp-4.0.9--utfcpp-4.0.9__LICENSE +23 -0
  212. package/runtime/native/binary/provenance.json +48 -0
  213. package/runtime/native/child-deadline-linux-x64 +0 -0
  214. package/runtime/native/child-deadline-linux.c +24 -0
  215. package/runtime/native/child-deadline-linux.provenance.json +17 -0
  216. package/runtime/native/deadline-alarm-darwin-universal.dylib +0 -0
  217. package/runtime/native/deadline-alarm.c +33 -0
  218. package/runtime/native/deadline-alarm.provenance.json +22 -0
  219. package/runtime/native/deadline-exec-darwin-arm64 +0 -0
  220. package/runtime/native/deadline-exec.c +24 -0
  221. package/runtime/native/deadline-exec.provenance.json +17 -0
  222. package/runtime/native/dnspy-extension/Bridge.cs +58 -0
  223. package/runtime/native/dnspy-extension/Insight.DnSpy.csproj +13 -0
  224. package/runtime/native/dnspy-extension/Insight.DnSpy.x.dll +0 -0
  225. package/runtime/native/dnspy-extension/NuGet.Config +1 -0
  226. package/runtime/native/dnspy-extension/UNICODE-LOADER.md +26 -0
  227. package/runtime/native/dnspy-extension/packages.lock.json +6 -0
  228. package/runtime/native/dnspy-extension/provenance.json +27 -0
  229. package/runtime/native/dnspy-extension/upstream-public-build.snk +0 -0
  230. package/runtime/native/dnspy-extension/vendor-files.json +4341 -0
  231. package/runtime/native/file-version.ps1 +7 -0
  232. package/runtime/native/insight-registry-win-x64.dll +0 -0
  233. package/runtime/native/mitmproxy/bridge.py +180 -0
  234. package/runtime/native/mitmproxy/notices.json +476 -0
  235. package/runtime/native/sources/detours-LICENSE.md +23 -0
  236. package/runtime/native/sources/detours-e4bfd6b.tar.gz +0 -0
  237. package/runtime/native/sources/detours-provenance.json +10 -0
  238. package/runtime/native/tshark-layout.json +2247 -0
  239. package/runtime/native/windows-job/DirectoryAlias.cs +24 -0
  240. package/runtime/native/windows-job/Insight.WindowsJob.csproj +1 -0
  241. package/runtime/native/windows-job/Insight.WindowsJob.dll +0 -0
  242. package/runtime/native/windows-job/NuGet.Config +1 -0
  243. package/runtime/native/windows-job/OwnedJob.cs +79 -0
  244. package/runtime/native/windows-job/RegistryRedirect.cs +45 -0
  245. package/runtime/native/windows-job/packages.lock.json +21 -0
  246. package/runtime/native/windows-job/provenance.json +16 -0
  247. package/runtime/native/windows-job/windows-job.ps1 +8 -0
  248. package/runtime/native/windows-registry.c +21 -0
  249. package/runtime/native/windows-registry.def +3 -0
  250. package/runtime/native/windows-registry.provenance.json +14 -0
  251. package/runtime/notices/diagnostics-10.0.750501.txt +23 -0
  252. package/runtime/tool-catalog.json +290 -0
  253. package/runtime/toolbox.json +1401 -0
  254. package/skill-bundle/insight-artifacts/SKILL.md +30 -0
  255. package/skill-bundle/insight-artifacts/references/agent-execution.md +36 -0
  256. package/skill-bundle/insight-artifacts/references/artifacts.md +52 -0
  257. package/skill-bundle/insight-binary/SKILL.md +46 -0
  258. package/skill-bundle/insight-binary/references/agent-execution.md +36 -0
  259. package/skill-bundle/insight-capture/SKILL.md +56 -0
  260. package/skill-bundle/insight-capture/references/agent-execution.md +36 -0
  261. package/skill-bundle/insight-cli/SKILL.md +42 -0
  262. package/skill-bundle/insight-cli/references/agent-execution.md +36 -0
  263. package/skill-bundle/insight-cli/references/agent-setup.md +61 -0
  264. package/skill-bundle/insight-die/SKILL.md +49 -0
  265. package/skill-bundle/insight-die/references/agent-execution.md +36 -0
  266. package/skill-bundle/insight-dnspy/SKILL.md +65 -0
  267. package/skill-bundle/insight-dnspy/references/agent-execution.md +36 -0
  268. package/skill-bundle/insight-dotnet-dump/SKILL.md +46 -0
  269. package/skill-bundle/insight-dotnet-dump/references/agent-execution.md +36 -0
  270. package/skill-bundle/insight-dotnet-stack/SKILL.md +39 -0
  271. package/skill-bundle/insight-dotnet-stack/references/agent-execution.md +36 -0
  272. package/skill-bundle/insight-dotnet-trace/SKILL.md +45 -0
  273. package/skill-bundle/insight-dotnet-trace/references/agent-execution.md +36 -0
  274. package/skill-bundle/insight-frida/SKILL.md +67 -0
  275. package/skill-bundle/insight-frida/references/agent-execution.md +36 -0
  276. package/skill-bundle/insight-ghidra/SKILL.md +91 -0
  277. package/skill-bundle/insight-ghidra/references/administration.md +34 -0
  278. package/skill-bundle/insight-ghidra/references/agent-execution.md +36 -0
  279. package/skill-bundle/insight-ghidra/references/archive.md +32 -0
  280. package/skill-bundle/insight-ghidra/references/artifacts.md +52 -0
  281. package/skill-bundle/insight-ghidra/references/debugger.md +62 -0
  282. package/skill-bundle/insight-ghidra/references/extensions-and-sync.md +124 -0
  283. package/skill-bundle/insight-ghidra/references/managed-runtime.md +157 -0
  284. package/skill-bundle/insight-ghidra/references/native-workflows.md +112 -0
  285. package/skill-bundle/insight-ghidra/references/query-semantics.md +96 -0
  286. package/skill-bundle/insight-ghidra/references/recovery.md +53 -0
  287. package/skill-bundle/insight-ghidra/references/research.md +101 -0
  288. package/skill-bundle/insight-ghidra/references/setup.md +50 -0
  289. package/skill-bundle/insight-ilspy/SKILL.md +45 -0
  290. package/skill-bundle/insight-ilspy/references/agent-execution.md +36 -0
  291. package/skill-bundle/insight-ilspy/references/ilspy.md +33 -0
  292. package/skill-bundle/insight-interop/SKILL.md +54 -0
  293. package/skill-bundle/insight-interop/references/agent-execution.md +36 -0
  294. package/skill-bundle/insight-lldb/SKILL.md +54 -0
  295. package/skill-bundle/insight-lldb/references/agent-execution.md +36 -0
  296. package/skill-bundle/insight-llvm/SKILL.md +56 -0
  297. package/skill-bundle/insight-llvm/references/agent-execution.md +36 -0
  298. package/skill-bundle/insight-managed-heap/SKILL.md +43 -0
  299. package/skill-bundle/insight-managed-heap/references/agent-execution.md +36 -0
  300. package/skill-bundle/insight-managed-metadata/SKILL.md +52 -0
  301. package/skill-bundle/insight-managed-metadata/references/agent-execution.md +36 -0
  302. package/skill-bundle/insight-mitmproxy/SKILL.md +62 -0
  303. package/skill-bundle/insight-mitmproxy/references/agent-execution.md +36 -0
  304. package/skill-bundle/insight-overview/SKILL.md +79 -0
  305. package/skill-bundle/insight-overview/references/agent-execution.md +36 -0
  306. package/skill-bundle/insight-procmon/SKILL.md +49 -0
  307. package/skill-bundle/insight-procmon/references/agent-execution.md +36 -0
  308. package/skill-bundle/insight-re/SKILL.md +121 -0
  309. package/skill-bundle/insight-re/references/agent-execution.md +36 -0
  310. package/skill-bundle/insight-re/references/artifacts.md +52 -0
  311. package/skill-bundle/insight-re/references/recovery.md +53 -0
  312. package/skill-bundle/insight-sevenzip/SKILL.md +42 -0
  313. package/skill-bundle/insight-sevenzip/references/agent-execution.md +36 -0
  314. package/skill-bundle/insight-strace/SKILL.md +46 -0
  315. package/skill-bundle/insight-strace/references/agent-execution.md +36 -0
  316. package/skill-bundle/insight-tshark/SKILL.md +49 -0
  317. package/skill-bundle/insight-tshark/references/agent-execution.md +36 -0
  318. package/skill-bundle/insight-windbg/SKILL.md +46 -0
  319. package/skill-bundle/insight-windbg/references/agent-execution.md +36 -0
  320. package/skill-bundle/manifest.json +32 -0
  321. package/skills/insight-artifacts/SKILL.md +30 -0
  322. package/skills/insight-artifacts/references/agent-execution.md +36 -0
  323. package/skills/insight-artifacts/references/artifacts.md +52 -0
  324. package/skills/insight-binary/SKILL.md +46 -0
  325. package/skills/insight-binary/references/agent-execution.md +36 -0
  326. package/skills/insight-capture/SKILL.md +56 -0
  327. package/skills/insight-capture/references/agent-execution.md +36 -0
  328. package/skills/insight-die/SKILL.md +49 -0
  329. package/skills/insight-die/references/agent-execution.md +36 -0
  330. package/skills/insight-dnspy/SKILL.md +65 -0
  331. package/skills/insight-dnspy/references/agent-execution.md +36 -0
  332. package/skills/insight-dotnet-dump/SKILL.md +46 -0
  333. package/skills/insight-dotnet-dump/references/agent-execution.md +36 -0
  334. package/skills/insight-dotnet-stack/SKILL.md +39 -0
  335. package/skills/insight-dotnet-stack/references/agent-execution.md +36 -0
  336. package/skills/insight-dotnet-trace/SKILL.md +45 -0
  337. package/skills/insight-dotnet-trace/references/agent-execution.md +36 -0
  338. package/skills/insight-frida/SKILL.md +67 -0
  339. package/skills/insight-frida/references/agent-execution.md +36 -0
  340. package/skills/insight-ghidra/SKILL.md +91 -0
  341. package/skills/insight-ghidra/references/administration.md +34 -0
  342. package/skills/insight-ghidra/references/agent-execution.md +36 -0
  343. package/skills/insight-ghidra/references/archive.md +32 -0
  344. package/skills/insight-ghidra/references/artifacts.md +52 -0
  345. package/skills/insight-ghidra/references/debugger.md +62 -0
  346. package/skills/insight-ghidra/references/extensions-and-sync.md +124 -0
  347. package/skills/insight-ghidra/references/managed-runtime.md +157 -0
  348. package/skills/insight-ghidra/references/native-workflows.md +112 -0
  349. package/skills/insight-ghidra/references/query-semantics.md +96 -0
  350. package/skills/insight-ghidra/references/recovery.md +53 -0
  351. package/skills/insight-ghidra/references/research.md +101 -0
  352. package/skills/insight-ghidra/references/setup.md +50 -0
  353. package/skills/insight-ilspy/SKILL.md +45 -0
  354. package/skills/insight-ilspy/references/agent-execution.md +36 -0
  355. package/skills/insight-ilspy/references/ilspy.md +33 -0
  356. package/skills/insight-interop/SKILL.md +54 -0
  357. package/skills/insight-interop/references/agent-execution.md +36 -0
  358. package/skills/insight-lldb/SKILL.md +54 -0
  359. package/skills/insight-lldb/references/agent-execution.md +36 -0
  360. package/skills/insight-llvm/SKILL.md +56 -0
  361. package/skills/insight-llvm/references/agent-execution.md +36 -0
  362. package/skills/insight-managed-heap/SKILL.md +43 -0
  363. package/skills/insight-managed-heap/references/agent-execution.md +36 -0
  364. package/skills/insight-managed-metadata/SKILL.md +52 -0
  365. package/skills/insight-managed-metadata/references/agent-execution.md +36 -0
  366. package/skills/insight-mitmproxy/SKILL.md +62 -0
  367. package/skills/insight-mitmproxy/references/agent-execution.md +36 -0
  368. package/skills/insight-overview/SKILL.md +79 -0
  369. package/skills/insight-overview/references/agent-execution.md +36 -0
  370. package/skills/insight-procmon/SKILL.md +49 -0
  371. package/skills/insight-procmon/references/agent-execution.md +36 -0
  372. package/skills/insight-re/SKILL.md +22 -9
  373. package/skills/insight-re/references/agent-execution.md +36 -0
  374. package/skills/insight-re/references/artifacts.md +52 -0
  375. package/skills/insight-re/references/recovery.md +53 -0
  376. package/skills/insight-sevenzip/SKILL.md +42 -0
  377. package/skills/insight-sevenzip/references/agent-execution.md +36 -0
  378. package/skills/insight-strace/SKILL.md +46 -0
  379. package/skills/insight-strace/references/agent-execution.md +36 -0
  380. package/skills/insight-tshark/SKILL.md +49 -0
  381. package/skills/insight-tshark/references/agent-execution.md +36 -0
  382. package/skills/insight-windbg/SKILL.md +46 -0
  383. package/skills/insight-windbg/references/agent-execution.md +36 -0
  384. package/dist/src/runtime-archives.d.ts +0 -5
@@ -0,0 +1,172 @@
1
+ import { command, Permission, CliError } from '@eyeauras/cli-factory';
2
+ import { dirname, join, resolve, basename } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { release } from 'node:os';
5
+ import { mkdir, readFile, stat, lstat, copyFile, cp, writeFile } from 'node:fs/promises';
6
+ import { readFileSync, constants } from 'node:fs';
7
+ import { randomUUID } from 'node:crypto';
8
+ import { ToolInstaller } from './tool-runtime/installer.js';
9
+ import { defineTool, lifecycleCommands } from './tool-runtime/definition.js';
10
+ import { catalogArtifact } from './tool-runtime/catalog.js';
11
+ import { runTool } from './tool-runtime/run.js';
12
+ import { atomicWrite, treeFingerprint, readJson } from './tool-runtime/store.js';
13
+ import { fileSha256 } from './tool-runtime/archives.js';
14
+ import { fail, text, id } from './model.js';
15
+ import { number } from './research.js';
16
+ const native = fileURLToPath(new URL('../../runtime/native/mitmproxy/', import.meta.url)), runtimeSha = '4bed6d0d2a0bcdc4afeb7408881c9b30e5f81b7c232c2ff9c987babcbed90125';
17
+ let notices;
18
+ function supported() { if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 24)
19
+ fail('unsupported', 'The pinned mitmproxy facade requires macOS 15+ ARM64. It uses only an owned loopback HTTP proxy and private profile CA; system proxy/trust settings are not installed.'); }
20
+ function bundle(executable) { if (basename(executable) !== 'mitmdump' || basename(dirname(executable)) !== 'MacOS' || basename(resolve(dirname(executable), '../..')) !== 'mitmproxy.app')
21
+ fail('configuration', 'Select the pinned mitmproxy.app/Contents/MacOS/mitmdump and its complete adjacent runtime.'); return resolve(dirname(executable), '../..'); }
22
+ export function mitmproxyInstaller(c) { return new ToolInstaller(c, { id: 'mitmproxy', primary: 'mitmproxy', preparationId: 'external-owned-copy-v1', prepareExternal: async (executable, stage) => { const source = bundle(executable), before = await treeFingerprint(source), owned = join(stage, 'execution/mitmproxy.app'); await cp(source, owned, { recursive: true, dereference: false, verbatimSymlinks: true, errorOnExist: true, force: false }); if (await treeFingerprint(source) !== before || await treeFingerprint(owned) !== before)
23
+ fail('binding', 'External mitmproxy runtime changed while making its owned execution copy.'); return { executable: join(owned, 'Contents/MacOS/mitmdump'), arguments: [], environment: {} }; }, components: () => { supported(); return { mitmproxy: catalogArtifact(runtimeSha) }; }, noticeFiles: notices ??= JSON.parse(readFileSync(join(native, 'notices.json'), 'utf8')), launch: roots => ({ executable: join(roots.mitmproxy, 'mitmproxy.app/Contents/MacOS/mitmdump'), arguments: [], environment: {} }), externalInputs: async (executable) => { supported(); return { runtimeFamily: await treeFingerprint(bundle(executable)) }; }, probe: async (launch, context) => { supported(); const result = await runTool(context, { tool: 'mitmproxy', role: 'version', executable: launch.executable, arguments: ['--version'], timeoutMs: 15000, maxOutputBytes: 65536, nativeDeadline: true }); if (!/^Mitmproxy: 12\.2\.3(?: binary)?\s*$/m.test(result.stdout))
24
+ fail('configuration', 'Select mitmproxy 12.2.3.'); return { version: '12.2.3', privatePython: '3.14.4', minimumSystem: 'macOS 15+ ARM64', typedHttpOnly: true, loopbackProxy: true, systemTrustInstalled: false, systemProxyInstalled: false }; } }); }
25
+ export async function mitmproxyStatus(c) {
26
+ const status = await mitmproxyInstaller(c).status(), captures = [];
27
+ for (const process of status.processes) {
28
+ if (process.role !== 'record' || process.state !== 'running')
29
+ continue;
30
+ const metadata = process.metadata ?? {}, directory = metadata.query;
31
+ if (typeof directory !== 'string' || !/^[-a-f0-9]{36}$/.test(basename(directory)) || directory !== join(c.appArguments.AppDataDirectory, 'runtime/mitmproxy/queries', basename(directory)))
32
+ continue;
33
+ let ready = false;
34
+ try {
35
+ const receipt = await readJson(join(directory, 'ready.json'));
36
+ ready = receipt?.schema === 1 && receipt.nonce === metadata.nonce && receipt.host === '127.0.0.1' && receipt.port === metadata.listenPort;
37
+ }
38
+ catch { }
39
+ captures.push({ process: process.id, state: ready ? 'ready' : 'starting', ready, ...(ready ? { endpoint: 'http://127.0.0.1:' + metadata.listenPort, archive: join(directory, 'capture.mitm'), caCertificate: join(directory, 'conf/mitmproxy-ca-cert.pem') } : {}) });
40
+ }
41
+ return { ...status, captures };
42
+ }
43
+ export function compareHttp(left, right) {
44
+ const index = (rows) => { const counts = new Map(); return new Map(rows.map(row => { const request = row.request.method + ' ' + row.request.url, n = counts.get(request) ?? 0; counts.set(request, n + 1); return [request + ' #' + n, row]; })); }, a = index(left), b = index(right), items = [];
45
+ let unchanged = 0;
46
+ for (const key of [...new Set([...a.keys(), ...b.keys()])].sort()) {
47
+ const l = a.get(key), r = b.get(key);
48
+ if (!l || !r) {
49
+ items.push({ key, state: l ? 'left_only' : 'right_only', left: l?.id, right: r?.id });
50
+ continue;
51
+ }
52
+ const changed = [], unknown = [];
53
+ if (l.request.bodyAvailable && r.request.bodyAvailable) {
54
+ if (l.request.bodySha256 !== r.request.bodySha256)
55
+ changed.push('request.bodySha256');
56
+ }
57
+ else
58
+ unknown.push('request.body');
59
+ if (l.response && r.response) {
60
+ if (l.response.statusCode !== r.response.statusCode)
61
+ changed.push('response.statusCode');
62
+ if (l.response.bodyAvailable && r.response.bodyAvailable) {
63
+ if (l.response.bodySha256 !== r.response.bodySha256)
64
+ changed.push('response.bodySha256');
65
+ }
66
+ else
67
+ unknown.push('response.body');
68
+ }
69
+ else
70
+ unknown.push('response');
71
+ if (l.error !== r.error)
72
+ changed.push('error');
73
+ if (l.pending || r.pending)
74
+ unknown.push('pending');
75
+ if (changed.length || unknown.length)
76
+ items.push({ key, state: changed.length ? 'changed' : 'unknown', left: l.id, right: r.id, changed, unknown });
77
+ else
78
+ unchanged++;
79
+ }
80
+ return { items, unchanged, scope: 'Literal method + URL, then occurrence order; selected body SHA256/status/error fields only. This alignment is a comparison aid, not proof of causal request correspondence. Volatile headers/timestamps are excluded; unavailable bodies remain unknown. Unmatched rows in a partial input do not prove absence.' };
81
+ }
82
+ async function bridge(c, selected, w, mode, o, input) {
83
+ const directory = join(c.appArguments.AppDataDirectory, 'runtime/mitmproxy/queries', randomUUID()), conf = join(directory, 'conf'), script = join(directory, 'bridge.py'), plan = join(directory, 'plan.json'), nonce = randomUUID(), bodyBytes = number(o.bodyBytes ?? 1024, 65536), maxFlows = number(o.maxFlows ?? 1000, 1000, 1), durationSeconds = mode === 'record' ? number(o.durationSeconds ?? 10, 300, 1) : undefined, port = mode === 'record' ? number(o.listenPort, 65535, 1) : undefined;
84
+ await mkdir(conf, { recursive: true, mode: 0o700 });
85
+ await copyFile(join(native, 'bridge.py'), script, constants.COPYFILE_EXCL);
86
+ const scriptSha = await fileSha256(script), capture = join(directory, 'capture.mitm'), caCertificate = join(conf, 'mitmproxy-ca-cert.pem');
87
+ const arguments_ = ['--set', 'confdir=' + conf, '--set', 'flow_detail=0', '--set', 'termlog_verbosity=error', '--set', 'body_size_limit=1m', '--set', 'websocket=false', '--set', 'rawtcp=false', '-s', script, ...(mode === 'record' ? ['--mode', 'regular', '--listen-host', '127.0.0.1', '--listen-port', String(port)] : ['--set', 'server=false'])];
88
+ let upstreamCaSha256;
89
+ if (o.upstreamCa) {
90
+ const path = resolve(c.cwd, text(o.upstreamCa, 4096)), artifact = await w.artifacts.capture(path, 'input');
91
+ if (artifact.size > 1024 ** 2)
92
+ fail('limit', 'Public upstream CA bundle exceeds 1 MiB.');
93
+ const body = await readFile(await w.artifacts.verify(artifact), 'utf8');
94
+ if (!body.includes('-----BEGIN CERTIFICATE-----') || body.includes('PRIVATE KEY'))
95
+ fail('invalid', 'Select a public PEM certificate bundle, without private keys.');
96
+ upstreamCaSha256 = artifact.sha256;
97
+ const captured = join(directory, 'upstream-ca.pem');
98
+ await copyFile(await w.artifacts.verify(artifact), captured, constants.COPYFILE_EXCL);
99
+ arguments_.push('--set', 'ssl_verify_upstream_trusted_ca=' + captured);
100
+ }
101
+ await atomicWrite(plan, { schema: 1, nonce, mode, bodyBytes, maxFlows, ...(mode === 'record' ? { durationSeconds, port } : { input: input.path }) });
102
+ let processResult;
103
+ try {
104
+ processResult = await runTool(c, { tool: 'mitmproxy', role: mode, installation: selected.id, executable: selected.executable, arguments: arguments_, environment: { HOME: join(directory, 'home'), INSIGHT_MITMPROXY_PLAN: plan }, nativeDeadline: true, timeoutMs: mode === 'record' ? durationSeconds * 1000 + 15000 : 60000, maxOutputBytes: 65536, target: input?.target, metadata: { mode, nonce, query: directory, bodyBytes, maxFlows, upstreamCaSha256, bridgeSha256: scriptSha, ...(mode === 'record' ? { listenHost: '127.0.0.1', listenPort: port, caCertificate, archive: capture, ready: join(directory, 'ready.json') } : { inputSha256: input.sha256 }) } });
105
+ }
106
+ catch (error) {
107
+ if (error instanceof CliError)
108
+ throw new CliError(error.message, { code: error.code, cause: error, result: { ...error.result, diagnostics: directory, retainedArchive: mode === 'record' ? capture : input.path, coverage: 'Interrupted or failed operation. Retained observations may be incomplete; no automatic recollection or traffic replay.', next: mode === 'record' ? ['insight-cli', 'mitmproxy', 'inspect', capture, '--json'] : undefined } });
109
+ throw error;
110
+ }
111
+ if ((await stat(join(directory, 'result.json'))).size > 512 * 1024)
112
+ fail('limit', 'Native observation receipt exceeds 512 KiB.');
113
+ const receipt = await readJson(join(directory, 'result.json'));
114
+ if (receipt?.schema !== 1 || receipt.nonce !== nonce || receipt.mode !== mode || typeof receipt.complete !== 'boolean' || !Number.isSafeInteger(receipt.httpFlows) || receipt.httpFlows < 0 || receipt.httpFlows > maxFlows)
115
+ fail('partial', 'Native HTTP observation receipt could not be verified.', { diagnostics: directory, process: processResult.process });
116
+ const report = join(directory, 'flows.jsonl');
117
+ if ((await stat(report)).size > 8 * 1024 ** 2)
118
+ fail('limit', 'Native HTTP report exceeds 8 MiB.');
119
+ const lines = (await readFile(report, 'utf8')).trim().split('\n').map(line => JSON.parse(line)), header = lines.shift();
120
+ if (header?.kind !== 'header' || header.schema !== 1 || header.nonce !== nonce || header.mode !== mode || lines.length !== receipt.httpFlows || lines.some(row => row.kind !== 'http' || typeof row.id !== 'string' || typeof row.request?.method !== 'string' || typeof row.request?.url !== 'string'))
121
+ fail('partial', 'Native HTTP report does not match its completed receipt.', { diagnostics: directory });
122
+ if (input && await fileSha256(input.path) !== input.sha256)
123
+ fail('binding', 'Captured native flow input changed during inspection.');
124
+ return { state: receipt.complete ? 'completed' : 'partial', complete: receipt.complete, reason: receipt.reason, skippedFlows: receipt.skippedFlows, pendingRequests: receipt.pendingRequests, error: receipt.error, tlsFailures: receipt.tlsFailures, upstreamCaSha256, process: processResult.process, elapsedMs: processResult.elapsedMs, diagnostics: directory, bodyBytes, maxFlows, items: lines, coverage: mode === 'record' ? 'One explicit loopback proxy observation window; HTTP request/response only. No system proxy/trust change, WebSocket payload or global absence claim. Native bodies are limited to 1 MiB each; archive to 64 MiB, JSON to 8 MiB.' : 'HTTP observations from one immutable native archive/HAR, bounded by max-flows/output. Partial/unsupported records and unavailable bodies remain unknown. An empty archive can reflect TLS/interception failure; retain its original window summary before inferring anything about traffic.', archive: mode === 'record' ? capture : undefined, ...(mode === 'record' ? { caCertificate, listenHost: '127.0.0.1', listenPort: port } : { target: input.target, inputSha256: input.sha256 }) };
125
+ }
126
+ async function captureInput(c, w, path, targetId) { if (Boolean(path) === Boolean(targetId))
127
+ fail('invalid', 'Supply one native flow archive/HAR path or --target.'); if (path) {
128
+ const source = resolve(c.cwd, text(path, 4096)), info = await lstat(source);
129
+ if (info.isFile() && info.size === 0) {
130
+ const directory = join(c.appArguments.AppDataDirectory, 'runtime/mitmproxy/empty-inputs', randomUUID());
131
+ await mkdir(directory, { recursive: true, mode: 0o700 });
132
+ const copy = join(directory, 'empty.mitm');
133
+ await copyFile(source, copy, constants.COPYFILE_EXCL);
134
+ if ((await stat(copy)).size !== 0 || (await stat(source)).size !== 0)
135
+ fail('binding', 'Empty archive changed while being captured.');
136
+ return { path: copy, sha256: await fileSha256(copy), target: undefined };
137
+ }
138
+ } const target = path ? await w.importTarget(resolve(c.cwd, text(path, 4096))) : w.target(id(targetId)); if (target.input.size > 64 * 1024 ** 2)
139
+ fail('limit', 'Native flow input exceeds 64 MiB.'); return { path: await w.artifacts.verify(target.input), target: target.id, sha256: target.binarySha256 }; }
140
+ async function ordinary(c, path, value) { const output = resolve(c.cwd, text(path, 4096)), content = JSON.stringify(value, null, 2) + '\n'; await mkdir(dirname(output), { recursive: true, mode: 0o700 }); await writeFile(output, content, { flag: 'wx', mode: 0o600 }); return { output, bytes: Buffer.byteLength(content) }; }
141
+ export function mitmproxyCommands(workspace) {
142
+ const installer = (c) => mitmproxyInstaller(c), definition = defineTool({ id: 'mitmproxy', description: 'Record, inspect and compare bounded HTTP observations through an owned loopback proxy', components: [{ id: 'mitmproxy', version: '12.2.3', artifacts: [] }], lifecycle: { download: (o, c) => installer(c).download(Boolean(o.offline)), install: (o, c) => installer(c).install(o), status: (_o, c) => mitmproxyStatus(c), doctor: (_o, c) => installer(c).doctor(), uninstall: (o, c) => installer(c).uninstall(Boolean(o.purgeCache)) } }), bounds = [{ flags: '--body-bytes <bytes>', description: 'Returned prefix per body (0–65536); full bounded body SHA is retained', defaultValue: 1024 }, { flags: '--max-flows <count>', description: 'Maximum inspected/recorded flows (1–1000)', defaultValue: 1000 }], paging = [{ flags: '--limit <count>', description: 'Return up to 1000 rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip matching rows', defaultValue: 0 }];
143
+ return [command('mitmproxy', definition.description, [...lifecycleCommands(definition), command('record', 'Record an explicit HTTP proxy window; clients must independently opt into its loopback endpoint', async ({ options: o }, c) => { supported(); if (o.listenPort === undefined)
144
+ fail('invalid', 'Select an explicit --listen-port for your own client. No system proxy is changed.'); if (o.output)
145
+ try {
146
+ await stat(resolve(c.cwd, text(o.output, 4096)));
147
+ fail('invalid', 'Capture output already exists.');
148
+ }
149
+ catch (error) {
150
+ if (error.code !== 'ENOENT')
151
+ throw error;
152
+ } const w = workspace(c); return installer(c).use(async (selected) => { const result = await bridge(c, selected, w, 'record', o); if (result.reason === 'interrupted')
153
+ throw new CliError('HTTP observation window was interrupted; inspect the retained archive explicitly.', { code: 'tool.interrupted', result: { state: 'partial', complete: false, reason: result.reason, process: result.process, diagnostics: result.diagnostics, retainedArchive: result.archive, totalFlows: result.items.length } }); const archiveSize = (await stat(result.archive)).size, target = archiveSize ? await w.importTarget(result.archive) : undefined; let output; if (o.output) {
154
+ output = resolve(c.cwd, text(o.output, 4096));
155
+ await mkdir(dirname(output), { recursive: true, mode: 0o700 });
156
+ await copyFile(result.archive, output, constants.COPYFILE_EXCL);
157
+ } const { items, ...base } = result; return { ...base, target: target?.id, inputSha256: target?.binarySha256 ?? await fileSha256(result.archive), archiveEmpty: archiveSize === 0, totalFlows: items.length, ...(output ? { output } : {}) }; }); }, { permission: Permission.Update, options: [...bounds, { flags: '--listen-port <port>', description: 'Required owned loopback HTTP proxy port' }, { flags: '--duration-seconds <seconds>', description: 'Observation window (1–300 seconds)', defaultValue: 10 }, { flags: '--upstream-ca <file>', description: 'Explicit public PEM CA for an owned HTTPS origin; never installed globally' }, { flags: '--output <file>', description: 'Copy completed native flow archive to a new ordinary file' }] }),
158
+ command('inspect [input]', 'Read retained native flow/HAR evidence without reconnecting or replaying traffic', async ({ args, options: o }, c) => { supported(); const view = text(o.view ?? 'overview', 16); if (!['overview', 'flows', 'flow'].includes(view) || (view === 'flow') !== Boolean(o.flowId))
159
+ fail('invalid', 'Use overview, flows or flow; only flow requires --flow-id.'); const limit = number(o.limit ?? 50, 1000, 1), offset = number(o.offset ?? 0, 1000000), w = workspace(c), input = await captureInput(c, w, args.input, o.target); return installer(c).use(async (selected) => { const result = await bridge(c, selected, w, 'inspect', o, input), { items: all, ...base } = result, items = all.filter(row => (!o.method || row.request.method === text(o.method, 32)) && (!o.urlContains || row.request.url.includes(text(o.urlContains, 4096))) && (!o.flowId || row.id === text(o.flowId, 128))); if (view === 'flow' && !items.length)
160
+ fail(result.complete ? 'notFound' : 'partial', 'Flow identity was not found in the inspected bounded input prefix.'); if (o.output)
161
+ return { ...base, ...await ordinary(c, o.output, { ...base, items, total: items.length }) }; if (view === 'overview') {
162
+ const methods = {}, statuses = {};
163
+ for (const row of items) {
164
+ methods[row.request.method] = (methods[row.request.method] ?? 0) + 1;
165
+ const status = String(row.response?.statusCode ?? 'unavailable');
166
+ statuses[status] = (statuses[status] ?? 0) + 1;
167
+ }
168
+ return { ...base, totalFlows: all.length, matchingFlows: items.length, methods, statuses, errors: items.filter(r => r.error).length, bodyPrefixesTruncated: items.filter(r => r.request.bodyTruncated || r.response?.bodyTruncated).length };
169
+ } return { ...base, items: view === 'flow' ? items : items.slice(offset, offset + limit), total: items.length, limit, offset, truncated: view !== 'flow' && offset + limit < items.length }; }); }, { permission: Permission.Update, options: [...bounds, ...paging, { flags: '--target <id>', description: 'Reuse an immutable native flow/HAR target' }, { flags: '--view <kind>', description: 'overview, flows or flow', defaultValue: 'overview' }, { flags: '--flow-id <id>', description: 'Native flow UUID from this exact archive' }, { flags: '--method <name>', description: 'Literal HTTP method filter' }, { flags: '--url-contains <text>', description: 'Literal URL substring filter, applied before pagination' }, { flags: '--output <file>', description: 'Save the full bounded selected HTTP rows to a new JSON file' }] }),
170
+ command('compare <left> <right>', 'Compare two retained HTTP observations without sending or replaying requests', async ({ args, options: o }, c) => { supported(); const limit = number(o.limit ?? 50, 1000, 1), offset = number(o.offset ?? 0, 1000000), w = workspace(c), left = await captureInput(c, w, args.left, undefined), right = await captureInput(c, w, args.right, undefined); return installer(c).use(async (selected) => { const a = await bridge(c, selected, w, 'inspect', o, left), b = await bridge(c, selected, w, 'inspect', o, right), compared = compareHttp(a.items, b.items), unknown = compared.items.some(row => row.state === 'unknown' || Array.isArray(row.unknown) && row.unknown.length), complete = a.complete && b.complete && !unknown, base = { state: complete ? 'completed' : 'partial', complete, left: { target: left.target, inputSha256: left.sha256, process: a.process, diagnostics: a.diagnostics, complete: a.complete }, right: { target: right.target, inputSha256: right.sha256, process: b.process, diagnostics: b.diagnostics, complete: b.complete }, unchanged: compared.unchanged, total: compared.items.length, scope: compared.scope }; if (o.output)
171
+ return { ...base, ...await ordinary(c, o.output, { ...base, items: compared.items }) }; return { ...base, items: compared.items.slice(offset, offset + limit), limit, offset, truncated: offset + limit < compared.items.length }; }); }, { permission: Permission.Update, options: [...bounds, ...paging, { flags: '--output <file>', description: 'Save full bounded comparison to a new ordinary JSON file' }] })])];
172
+ }
@@ -1,3 +1,4 @@
1
+ import { type RunContext } from './tool-runtime/run.js';
1
2
  export interface NativeInputs {
2
3
  java: string;
3
4
  ghidraHome: string;
@@ -22,7 +23,7 @@ export interface NativeRuntimeFile {
22
23
  /** Installed native code/data, excluding documentation and isolated generated caches. */
23
24
  export declare function nativeRuntimeFiles(ghidraHome: string, java: string): Promise<NativeRuntimeFile[]>;
24
25
  export declare function nativeRuntimeFingerprint(ghidraVersion: string, files: NativeRuntimeFile[]): Promise<string>;
25
- export declare function nativeInputs(values: Record<string, unknown>, directory?: string): Promise<NativeInputs>;
26
+ export declare function nativeInputs(values: Record<string, unknown>, directory?: string, c?: RunContext): Promise<NativeInputs>;
26
27
  /** Compile packaged helper sources against the selected installation, never an author checkout. */
27
- export declare function nativeHelpers(directory: string, inputs: NativeInputs): Promise<string>;
28
+ export declare function nativeHelpers(directory: string, inputs: NativeInputs, c?: RunContext): Promise<string>;
28
29
  export declare const nativeExtensionArguments: (inputs: NativeInputs) => string[];
@@ -1,3 +1,4 @@
1
+ import { runTool } from './tool-runtime/run.js';
1
2
  import { createHash, randomUUID } from 'node:crypto';
2
3
  import { readFile, writeFile, readdir, mkdir, open, rename, rm, realpath, stat } from 'node:fs/promises';
3
4
  import { basename, delimiter, dirname, isAbsolute, join, relative, sep } from 'node:path';
@@ -78,7 +79,7 @@ export async function nativeRuntimeFingerprint(ghidraVersion, files) {
78
79
  hashes.push({ name: file.name, sha256: await sha(file.path) });
79
80
  return createHash('sha256').update(stable({ schema: 2, ghidraVersion, hashes })).digest('hex');
80
81
  }
81
- export async function nativeInputs(values, directory) {
82
+ export async function nativeInputs(values, directory, c) {
82
83
  if (directory)
83
84
  values = runtimeValues(dirname(directory), values);
84
85
  if (!values.java || !values.ghidraHome)
@@ -96,7 +97,7 @@ export async function nativeInputs(values, directory) {
96
97
  fail('configuration', 'This build requires the verified Ghidra 12.1.2 runtime.');
97
98
  let jdk;
98
99
  try {
99
- jdk = await run(java, ['--version'], { timeout: 10000, maxBuffer: 16384 });
100
+ jdk = c ? await runTool(c, { tool: 'ghidra', role: 'java-version', executable: java, arguments: ['--version'], timeoutMs: 10000, maxOutputBytes: 16384 }) : await run(java, ['--version'], { timeout: 10000, maxBuffer: 16384 });
100
101
  }
101
102
  catch {
102
103
  fail('configuration', 'Configured Java executable could not be verified.');
@@ -130,7 +131,7 @@ export async function nativeInputs(values, directory) {
130
131
  return { java, ghidraHome, mcpJar, jars, classpath: jars.join(delimiter), ghidraVersion, fingerprint, debuggerWheels, extensionRoots: modules.map(m => m.root), serverClasspath: baseJars.join(delimiter) };
131
132
  }
132
133
  /** Compile packaged helper sources against the selected installation, never an author checkout. */
133
- export async function nativeHelpers(directory, inputs) {
134
+ export async function nativeHelpers(directory, inputs, c) {
134
135
  const sources = fileURLToPath(new URL('../../references/native/', import.meta.url));
135
136
  const names = [...(await readdir(sources)).filter(name => name.endsWith('.java')), '../InsightRepositoryProbe.java'].sort();
136
137
  if (!names.length)
@@ -153,7 +154,11 @@ export async function nativeHelpers(directory, inputs) {
153
154
  const temporary = join(parent, 'compiling-' + randomUUID());
154
155
  await mkdir(temporary, { mode: 0o700 });
155
156
  try {
156
- await run(join(dirname(inputs.java), 'javac' + (process.platform === 'win32' ? '.exe' : '')), ['-proc:none', '-cp', inputs.classpath, '-d', temporary, ...names.map(name => join(sources, name))], { timeout: 60000, maxBuffer: 262144 });
157
+ const executable = join(dirname(inputs.java), 'javac' + (process.platform === 'win32' ? '.exe' : '')), args = ['-proc:none', '-cp', inputs.classpath, '-d', temporary, ...names.map(name => join(sources, name))];
158
+ if (c)
159
+ await runTool(c, { tool: 'ghidra', role: 'compile-helpers', installation: inputs.fingerprint, executable, arguments: args, timeoutMs: 60000, maxOutputBytes: 262144 });
160
+ else
161
+ await run(executable, args, { timeout: 60000, maxBuffer: 262144 });
157
162
  const complete = await open(join(temporary, 'complete'), 'wx', 0o600);
158
163
  try {
159
164
  await complete.writeFile(key);
@@ -0,0 +1 @@
1
+ export declare const packageVersion: string;
@@ -0,0 +1,3 @@
1
+ import { readFileSync } from 'node:fs';
2
+ // The installed manifest is also covered by Factory's package build identity.
3
+ export const packageVersion = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version;
@@ -0,0 +1,2 @@
1
+ /** Must be verified with the pinned ProcMon before an adapter admits active capture. */
2
+ export declare function procmonConfiguration(pid: number, path?: string): Buffer<ArrayBuffer>;
@@ -0,0 +1,15 @@
1
+ // First-party serializer of the public PMC format research, not a Python runtime dependency.
2
+ // https://github.com/eronnen/procmon-parser/blob/96080961e51745ddc6e83490c24e540553c44c71/docs/PMC%20Format.md
3
+ import { fail } from './model.js';
4
+ const u32 = (value) => { const bytes = Buffer.alloc(4); bytes.writeUInt32LE(value); return bytes; };
5
+ const record = (name, data) => { const key = Buffer.from(name + '\0', 'utf16le'); return Buffer.concat([u32(16 + key.length + data.length), u32(16), u32(16 + key.length), u32(data.length), key, data]); };
6
+ const rule = (column, value, numeric = 0) => { const bytes = Buffer.from(value + '\0', 'utf16le'); return Buffer.concat([u32(column), u32(0), Buffer.from([1]), u32(bytes.length), bytes, u32(numeric), u32(0)]); };
7
+ /** Must be verified with the pinned ProcMon before an adapter admits active capture. */
8
+ export function procmonConfiguration(pid, path) {
9
+ if (!Number.isSafeInteger(pid) || pid < 1 || pid > 0xffffffff)
10
+ fail('invalid', 'A positive owned Windows PID is required.');
11
+ if (path !== undefined && (!path || /[\x00-\x1f]/.test(path) || path.length > 4096))
12
+ fail('invalid', 'ProcMon path must be a bounded literal native path without control characters.');
13
+ const rules = [rule(40054, String(pid), pid), ...(path ? [rule(40071, path)] : [])];
14
+ return Buffer.concat([record('FilterRules', Buffer.concat([Buffer.from([1]), u32(rules.length), ...rules])), record('DestructiveFilter', u32(1)), record('Profiling', u32(0)), record('ResolveAddresses', u32(0)), record('Autoscroll', u32(0)), record('HistoryDepth', u32(1)), record('AdvancedMode', u32(0))]);
15
+ }
@@ -0,0 +1,13 @@
1
+ export interface ProcmonEvent {
2
+ time: string;
3
+ process: string;
4
+ pid: number;
5
+ operation: string;
6
+ path: string;
7
+ result: string;
8
+ detail: string;
9
+ duration?: string;
10
+ }
11
+ /** Parse complete, bounded native CSV rather than splitting quoted paths/details at commas. */
12
+ export declare function procmonEvents(bytes: Buffer): ProcmonEvent[];
13
+ export declare function procmonScope(events: ProcmonEvent[], pid: number, path?: string): ProcmonEvent[];
@@ -0,0 +1,82 @@
1
+ import { fail } from './model.js';
2
+ /** Parse complete, bounded native CSV rather than splitting quoted paths/details at commas. */
3
+ export function procmonEvents(bytes) {
4
+ if (bytes.length > 16 * 1024 ** 2)
5
+ fail('limit', 'Native ProcMon CSV exceeds 16 MiB; retained diagnostics are incomplete.');
6
+ let source;
7
+ try {
8
+ const marker = bytes.subarray(0, 2).toString('hex');
9
+ source = new TextDecoder(marker === 'fffe' ? 'utf-16le' : marker === 'feff' ? 'utf-16be' : 'utf-8', { fatal: true }).decode(bytes);
10
+ }
11
+ catch {
12
+ fail('partial', 'Native ProcMon CSV encoding is invalid; retained bytes were not replaced.');
13
+ }
14
+ if (source.includes('\0'))
15
+ fail('partial', 'Native ProcMon CSV contains invalid text.');
16
+ const rows = [];
17
+ let row = [], value = '', quoted = false, closed = false;
18
+ const cell = () => { if (row.length >= 64)
19
+ fail('limit', 'Native ProcMon CSV exceeds its column bound.'); row.push(value); value = ''; closed = false; };
20
+ const record = () => { cell(); if (row.some(x => x.length))
21
+ rows.push(row); row = []; if (rows.length > 100001)
22
+ fail('limit', 'Native ProcMon CSV exceeds 100000 event rows.'); };
23
+ for (let i = 0; i < source.length; i++) {
24
+ const c = source[i];
25
+ if (quoted) {
26
+ if (c === '"') {
27
+ if (source[i + 1] === '"') {
28
+ value += '"';
29
+ i++;
30
+ }
31
+ else {
32
+ quoted = false;
33
+ closed = true;
34
+ }
35
+ }
36
+ else
37
+ value += c;
38
+ continue;
39
+ }
40
+ if (c === '"') {
41
+ if (value || closed)
42
+ fail('partial', 'Native ProcMon CSV has an invalid quote.');
43
+ quoted = true;
44
+ }
45
+ else if (c === ',')
46
+ cell();
47
+ else if (c === '\n' || c === '\r') {
48
+ if (c === '\r' && source[i + 1] === '\n')
49
+ i++;
50
+ record();
51
+ }
52
+ else {
53
+ if (closed)
54
+ fail('partial', 'Native ProcMon CSV has text after a quoted cell.');
55
+ value += c;
56
+ }
57
+ }
58
+ if (quoted)
59
+ fail('partial', 'Native ProcMon CSV ends inside a quoted value.');
60
+ if (value || row.length || closed)
61
+ record();
62
+ const header = rows.shift();
63
+ if (!header)
64
+ fail('partial', 'Native ProcMon CSV has no header.');
65
+ const columns = ['Process Name', 'PID', 'Operation', 'Path', 'Result', 'Detail'], indices = Object.fromEntries(columns.map(name => [name, header.indexOf(name)]));
66
+ if (Object.values(indices).some(i => i < 0) || new Set(header).size !== header.length)
67
+ fail('partial', 'Native ProcMon CSV has an unsupported header.');
68
+ const time = header.indexOf('Time of Day') >= 0 ? header.indexOf('Time of Day') : header.indexOf('Date & Time'), duration = header.indexOf('Duration');
69
+ return rows.map(row => {
70
+ if (row.length !== header.length || !/^\d+$/.test(row[indices.PID]))
71
+ fail('partial', 'Native ProcMon CSV has a malformed event.');
72
+ const pid = Number(row[indices.PID]);
73
+ if (!Number.isSafeInteger(pid) || pid > 0xffffffff)
74
+ fail('partial', 'Native ProcMon CSV PID is invalid.');
75
+ return { time: time >= 0 ? row[time] : '', process: row[indices['Process Name']], pid, operation: row[indices.Operation], path: row[indices.Path], result: row[indices.Result], detail: row[indices.Detail], ...(duration >= 0 ? { duration: row[duration] } : {}) };
76
+ });
77
+ }
78
+ export function procmonScope(events, pid, path) {
79
+ if (events.some(e => e.pid !== pid || path !== undefined && e.path.toLowerCase() !== path.toLowerCase()))
80
+ fail('partial', 'Native ProcMon capture scope was not established; no foreign events were returned.');
81
+ return events;
82
+ }
@@ -0,0 +1,4 @@
1
+ import { type CommandContext, type CommandDefinition } from '@eyeauras/cli-factory';
2
+ import { ToolInstaller } from './tool-runtime/installer.js';
3
+ export declare function procmonInstaller(c: CommandContext): ToolInstaller;
4
+ export declare function procmonCommands(): CommandDefinition[];
@@ -0,0 +1,107 @@
1
+ import { command, Permission, CliError } from '@eyeauras/cli-factory';
2
+ import { dirname, join, resolve, basename } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { mkdir, writeFile, readFile, stat } from 'node:fs/promises';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { atomicWrite, readJson } from './tool-runtime/store.js';
7
+ import { fileSha256 } from './tool-runtime/archives.js';
8
+ import { processStatus } from './tool-runtime/supervisor.js';
9
+ import { ToolInstaller } from './tool-runtime/installer.js';
10
+ import { defineTool, lifecycleCommands } from './tool-runtime/definition.js';
11
+ import { catalogArtifact } from './tool-runtime/catalog.js';
12
+ import { runTool } from './tool-runtime/run.js';
13
+ import { processIdentity } from './tool-runtime/identity.js';
14
+ import { procmonConfiguration } from './procmon-config.js';
15
+ import { procmonEvents, procmonScope } from './procmon-events.js';
16
+ import { fail, text } from './model.js';
17
+ import { number } from './research.js';
18
+ function supported() { if (process.platform !== 'win32' || process.arch !== 'x64')
19
+ fail('unsupported', 'ProcMon capture requires Windows x64 and an elevated authorized owner.'); }
20
+ const powershell = () => { const root = process.env.SystemRoot ?? process.env.WINDIR; if (!root)
21
+ fail('configuration', 'Windows system directory is unavailable.'); return join(root, 'System32/WindowsPowerShell/v1.0/powershell.exe'); };
22
+ async function metadata(c, executable) { const r = await runTool(c, { tool: 'procmon', role: executable ? 'version' : 'privilege', executable: powershell(), arguments: ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', fileURLToPath(new URL('../../runtime/native/file-version.ps1', import.meta.url)), ...(executable ? ['-Executable', executable] : ['-Administrator'])], nativeDeadline: true, timeoutMs: 15000, maxOutputBytes: 65536 }); return r.stdout.trim(); }
23
+ export function procmonInstaller(c) { return new ToolInstaller(c, { id: 'procmon', primary: 'procmon', components: () => { supported(); return { procmon: catalogArtifact('477754bf299c9e5b311c5666f7a4a48dfdb21265eaa8f0cca70ef9d9552e3a10') }; }, launch: roots => ({ executable: join(roots.procmon, 'Procmon64.exe'), arguments: [], environment: {} }), externalInputs: async (executable) => { supported(); if (basename(executable).toLowerCase() !== 'procmon64.exe')
24
+ fail('configuration', 'Select the ProcMon64.exe x64 executable.'); return {}; }, probe: async (launch, context) => { supported(); const version = await metadata(context, launch.executable); if (!/^4\.12(?:\.[0-9]+)*$/.test(version))
25
+ fail('configuration', 'Select Process Monitor 4.12.', { observedVersion: version }); return { version, codeMetadataVerified: true, captureRequiresAdministrator: true, elevatedOwner: await metadata(context) === 'true', captureScope: 'explicit existing PID and optional native path; original process lifetime preserved' }; } }); }
26
+ async function captureEvents(c, record) {
27
+ const directory = c.appArguments.AppDataDirectory, meta = record.metadata ?? {}, root = String(meta.captureDirectory ?? ''), pid = Number(meta.subjectPid), nativePath = meta.nativePath === undefined ? undefined : String(meta.nativePath);
28
+ if (record.tool !== 'procmon' || record.role !== 'observe' || !['exited', 'failed'].includes(record.state) || !Number.isSafeInteger(pid) || pid < 1 || !/^[a-f0-9-]{36}$/.test(basename(root)) || root !== join(directory, 'runtime/procmon/captures', basename(root)))
29
+ fail('configuration', 'Select a terminal owned ProcMon observation; active or unverified captures are retained.');
30
+ const pml = join(root, 'events.pml');
31
+ if ((await stat(pml)).size > 64 * 1024 ** 2)
32
+ fail('limit', 'Retained native PML exceeds the 64 MiB query bound.', { diagnostics: root });
33
+ const pmlSha256 = await fileSha256(pml), receiptPath = join(root, 'export.json'), cached = await readJson(receiptPath);
34
+ let csv, exportProcess;
35
+ if (cached) {
36
+ if (cached.schema !== 1 || typeof cached.csv !== 'string' || typeof cached.csvSha256 !== 'string' || typeof cached.process !== 'string' || !/^[a-f0-9-]{36}$/.test(cached.process) || cached.pmlSha256 !== pmlSha256 || cached.csv !== join(root, basename(cached.csv)) || !/^export-[a-f0-9-]{36}\.csv$/.test(basename(cached.csv)) || await fileSha256(cached.csv) !== cached.csvSha256)
37
+ fail('binding', 'Retained ProcMon export differs from its verified bytes.');
38
+ csv = cached.csv;
39
+ exportProcess = cached.process;
40
+ }
41
+ else {
42
+ csv = join(root, 'export-' + randomUUID() + '.csv');
43
+ const exported = await procmonInstaller(c).use(selected => runTool(c, { tool: 'procmon', role: 'export', installation: selected.id, executable: selected.executable, arguments: ['/AcceptEula', '/Quiet', '/NoConnect', '/NoFilter', '/OpenLog', pml, '/SaveAs', csv], nativeDeadline: true, nativeRegistry: 'procmon', nativeMutex: 'procmon', timeoutMs: 30000 }));
44
+ exportProcess = exported.process;
45
+ if (await fileSha256(pml) !== pmlSha256)
46
+ fail('binding', 'Native PML changed during export; no complete query was assumed.');
47
+ if ((await stat(csv)).size > 16 * 1024 ** 2)
48
+ fail('limit', 'ProcMon CSV exceeds 16 MiB; raw capture is retained.', { diagnostics: root });
49
+ procmonScope(procmonEvents(await readFile(csv)), pid, nativePath);
50
+ await atomicWrite(receiptPath, { schema: 1, pmlSha256, csv, csvSha256: await fileSha256(csv), process: exportProcess });
51
+ }
52
+ if ((await stat(csv)).size > 16 * 1024 ** 2)
53
+ fail('limit', 'ProcMon CSV exceeds 16 MiB.');
54
+ return { events: procmonScope(procmonEvents(await readFile(csv)), pid, nativePath), exportProcess, diagnostics: root };
55
+ }
56
+ async function report(c, record, o) {
57
+ const limit = number(o.limit ?? 100, 1000, 1), offset = number(o.offset ?? 0, 1000000), { events, exportProcess, diagnostics } = await captureEvents(c, record), operations = {};
58
+ for (const e of events) {
59
+ const key = e.operation + ' / ' + e.result;
60
+ operations[key] = (operations[key] ?? 0) + 1;
61
+ }
62
+ const complete = record.outcome === 'completed', base = { state: complete ? 'completed' : 'partial', complete, subject: { pid: record.metadata.subjectPid, birth: record.metadata.subjectBirth }, durationSeconds: record.metadata.durationSeconds, ...(record.metadata.nativePath ? { nativePath: record.metadata.nativePath } : {}), process: record.id, exportProcess, elapsedMs: record.elapsedMs, diagnostics, operations, coverage: 'Only the explicit existing PID, optional native path and observed interval. Earlier and filtered behavior is unknown. An empty window does not establish absence. Interrupted/lost collector outcomes remain partial. Native PML/CSV stay private under profile diagnostics.' };
63
+ if (o.output) {
64
+ const output = resolve(c.cwd, text(o.output, 4096)), content = JSON.stringify({ ...base, events }, null, 2) + '\n';
65
+ await mkdir(dirname(output), { recursive: true, mode: 0o700 });
66
+ await writeFile(output, content, { flag: 'wx', mode: 0o600 });
67
+ return { ...base, output, bytes: Buffer.byteLength(content), totalEvents: events.length };
68
+ }
69
+ return { ...base, events: events.slice(offset, offset + limit), offset, limit, totalEvents: events.length, truncated: offset + limit < events.length };
70
+ }
71
+ const outputOptions = [{ flags: '--output <file>', description: 'Save full bounded JSON to a new ordinary file' }, { flags: '--limit <count>', description: 'Maximum events to display (1–1000)', defaultValue: 100 }, { flags: '--offset <count>', description: 'Skip events', defaultValue: 0 }];
72
+ export function procmonCommands() {
73
+ const definition = defineTool({ id: 'procmon', description: 'Observe scoped file, registry and process activity in an existing authorized Windows process', vendorDirect: true, components: [{ id: 'procmon', version: '4.12', artifacts: [] }], lifecycle: { download: (o, c) => procmonInstaller(c).download(Boolean(o.offline), Boolean(o.vendorDirect)), install: (o, c) => procmonInstaller(c).install(o), uninstall: (o, c) => procmonInstaller(c).uninstall(Boolean(o.purgeCache)), doctor: (_o, c) => procmonInstaller(c).doctor(), status: (_o, c) => procmonInstaller(c).status() } });
74
+ return [command('procmon', definition.description, [...lifecycleCommands(definition), command('observe', 'Record a bounded prefiltered interval without owning the original process lifetime', async ({ options: o }, c) => {
75
+ supported();
76
+ const pid = number(o.pid, 2147483647, 1), duration = number(o.durationSeconds ?? 5, 30, 1), path = o.path === undefined ? undefined : text(o.path, 4096), configuration = procmonConfiguration(pid, path);
77
+ const subject = await processIdentity(pid);
78
+ if (!subject?.strong || !/^\d+$/.test(subject.birth))
79
+ fail('configuration', 'The explicit Windows subject PID is unavailable or its birth identity cannot be verified.');
80
+ if (await metadata(c) !== 'true')
81
+ fail('configuration', 'ProcMon capture requires an elevated insight-cli owner. Stop the current owner and invoke from an authorized elevated terminal.');
82
+ const directory = join(c.appArguments.AppDataDirectory, 'runtime/procmon/captures', randomUUID()), pmc = join(directory, 'scope.pmc'), pml = join(directory, 'events.pml');
83
+ await mkdir(directory, { recursive: true, mode: 0o700 });
84
+ await writeFile(pmc, configuration, { flag: 'wx', mode: 0o600 });
85
+ return procmonInstaller(c).use(async (selected) => {
86
+ if ((await processIdentity(pid))?.birth !== subject.birth)
87
+ fail('binding', 'Original process identity changed before capture.');
88
+ let capture;
89
+ try {
90
+ capture = await runTool(c, { tool: 'procmon', role: 'observe', installation: selected.id, executable: selected.executable, arguments: ['/AcceptEula', '/Quiet', '/Minimized', '/LoadConfig', pmc, '/BackingFile', pml, '/Runtime', String(duration)], nativeDeadline: true, nativeRegistry: 'procmon', nativeMutex: 'procmon', observedSubject: { pid, birth: subject.birth }, timeoutMs: (duration + 20) * 1000, acceptedCodes: [0, 1], metadata: { subjectPid: pid, subjectBirth: subject.birth, durationSeconds: duration, ...(path ? { nativePath: path } : {}), captureDirectory: directory } });
91
+ }
92
+ catch (error) {
93
+ const retained = error instanceof CliError ? error.result?.process : undefined;
94
+ if (error instanceof CliError && typeof retained === 'string')
95
+ throw new CliError(error.message, { code: error.code, cause: error, result: { ...error.result, captureProcess: retained, nextCommand: 'insight-cli procmon inspect ' + retained } });
96
+ throw error;
97
+ }
98
+ try {
99
+ return await report(c, await processStatus(c.appArguments.AppDataDirectory, capture.process), o);
100
+ }
101
+ catch (error) {
102
+ throw new CliError(error instanceof Error ? error.message : 'Retained capture could not be queried.', { code: error instanceof CliError ? error.code : 'coordinator.partial', cause: error, result: { captureProcess: capture.process, diagnostics: directory, nextCommand: 'insight-cli procmon inspect ' + capture.process } });
103
+ }
104
+ });
105
+ }, { permission: Permission.Update, options: [{ flags: '--pid <number>', description: 'Required explicit authorized running Windows PID' }, { flags: '--duration-seconds <seconds>', description: 'Native observation interval (1–30)', defaultValue: 5 }, { flags: '--path <native-path>', description: 'Optional exact native path, such as a file path or HKCU registry path' }, ...outputOptions] }), command('inspect <process>', 'Read or export a retained terminal observation without collecting another interval', async ({ args, options: o }, c) => { supported(); const process = text(args.process, 36); if (!/^[a-f0-9-]{36}$/.test(process))
106
+ fail('invalid', 'Select an owned observation process ID.'); return report(c, await processStatus(c.appArguments.AppDataDirectory, process), o); }, { permission: Permission.Update, options: outputOptions })])];
107
+ }
@@ -127,9 +127,18 @@ export declare class Research {
127
127
  session: string;
128
128
  target: string;
129
129
  }>;
130
- function(selected: Scope, at: string, decompile?: boolean): Promise<{
131
- code?: unknown;
130
+ function(selected: Scope, at: string, decompile?: boolean, page?: {
131
+ limit: number;
132
+ offset: number;
133
+ }): Promise<{
134
+ textSha256?: string | undefined;
135
+ totalCharacters?: number | undefined;
136
+ limit?: number | undefined;
137
+ offset?: number | undefined;
138
+ sourceTruncated?: boolean | undefined;
132
139
  truncated?: boolean | undefined;
140
+ coordinates?: string | undefined;
141
+ code?: string | undefined;
133
142
  address: string;
134
143
  name: unknown;
135
144
  signature: string;
@@ -1,3 +1,4 @@
1
+ import { textWindow } from './text-window.js';
1
2
  import { fail, id, object, text, digest } from './model.js';
2
3
  import { fieldKey, scalarMerge, scalarRefresh } from './merge.js';
3
4
  import { verifyMutation } from './mutation-effects.js';
@@ -256,7 +257,7 @@ export class Research {
256
257
  return { ...selected, items, offset, limit, total: page.total, truncated: object(value).truncated === true || offset + items.length < page.total,
257
258
  ...(object(value).scan ? { scan: object(value).scan, totalKnown: object(value).total_known !== false } : {}) };
258
259
  }
259
- async function(selected, at, decompile = false) {
260
+ async function(selected, at, decompile = false, page) {
260
261
  return this.ordered(selected, async () => {
261
262
  const backend = await this.backend();
262
263
  await backend.open(selected);
@@ -267,8 +268,9 @@ export class Research {
267
268
  if (decompile && typeof result.decompiled_code !== 'string')
268
269
  fail('partial', 'Function decompilation did not produce text.');
269
270
  const listing = object(await backend.call(selected, '/get_comment', { address: result.entry_point }));
270
- return { ...selected, address: publicAddress(result.entry_point), name: result.name, signature: result.signature, comments: comments(listing),
271
- ...(decompile ? { code: result.decompiled_code, truncated: Boolean(object(result.truncation ?? {}).decompiled_code) } : {}) };
271
+ const window = decompile ? textWindow(String(result.decompiled_code), page?.limit ?? 16000, page?.offset ?? 0, Boolean(object(result.truncation ?? {}).decompiled_code)) : undefined;
272
+ const { content, ...paging } = window ?? { content: undefined };
273
+ return { ...selected, address: publicAddress(result.entry_point), name: result.name, signature: result.signature, comments: comments(listing), ...(window ? { code: content, ...paging } : {}) };
272
274
  });
273
275
  }
274
276
  async xrefs(selected, at, limit, offset) {
@@ -1,18 +1,13 @@
1
- export interface RuntimeArtifact {
2
- name: string;
3
- url: string;
4
- sha256: string;
5
- format: 'zip' | 'tgz';
6
- root: string;
7
- license: string;
1
+ import type { ToolArtifact } from './tool-runtime/definition.js';
2
+ export interface RuntimeArtifact extends ToolArtifact {
8
3
  }
9
- export declare const ghidraArchive: RuntimeArtifact;
4
+ export declare const ghidraArchive: ToolArtifact;
10
5
  export declare function runtimeCatalog(platform?: string, arch?: string, kernel?: string): {
11
6
  schema: number;
12
7
  ghidraVersion: string;
13
8
  javaVersion: string;
14
9
  platform: string;
15
10
  architecture: string;
16
- ghidra: RuntimeArtifact;
17
- java: RuntimeArtifact;
11
+ ghidra: ToolArtifact;
12
+ java: ToolArtifact;
18
13
  };
@@ -1,7 +1,7 @@
1
1
  import { release } from 'node:os';
2
2
  import { fail } from './model.js';
3
- const github = 'https://github.com/';
4
- export const ghidraArchive = { name: 'ghidra-12.1.2', url: github + 'NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.2_build/ghidra_12.1.2_PUBLIC_20260605.zip', sha256: 'b62e81a0390618466c019c60d8c2f796ced2509c4c1aea4a37644a77272cf99d', format: 'zip', root: 'ghidra_12.1.2_PUBLIC', license: 'Apache-2.0 and included third-party licenses' };
3
+ import { catalogArtifact } from './tool-runtime/catalog.js';
4
+ export const ghidraArchive = catalogArtifact('b62e81a0390618466c019c60d8c2f796ced2509c4c1aea4a37644a77272cf99d');
5
5
  const bottles = { arm64_sonoma: '40f68357d6b62a08429c36228907c995e3449283b6d2e08ba5a4e30b53a09725', arm64_sequoia: '90aa942184fca2337ad0a123f818f37372ea642e8e69e969d45cc144a6f26fdf', arm64_tahoe: '079007d8a3a477c8d5901e6596947612d86c8641956424a2bcb71ecd798bedcc', sonoma: 'e30f8c84b64331f87f6ef1890cbdded6672bb7fcc8b674794ac93e4b3e62ad2b' };
6
6
  const jdks = {
7
7
  'darwin-arm64': ['aarch64_mac', '6ebcf221c9b41507b14c098e93c6ead6440b8d9bd154f8ec666c4c73abbdb201'],
@@ -13,15 +13,14 @@ export function runtimeCatalog(platform = process.platform, arch = process.arch,
13
13
  const jdk = jdks[platform + '-' + arch];
14
14
  if (!jdk)
15
15
  fail('configuration', 'No verified managed runtime for this OS/architecture; use an external compatible Ghidra installation.');
16
- const windows = platform === 'win32', format = windows ? 'zip' : 'tgz', extension = windows ? 'zip' : 'tar.gz';
17
- const java = { name: 'temurin-21.0.11+10-' + platform + '-' + arch, url: github + 'adoptium/temurin21-binaries/releases/download/jdk-21.0.11%2B10/OpenJDK21U-jdk_' + jdk[0] + '_hotspot_21.0.11_10.' + extension, sha256: jdk[1], format, root: 'jdk-21.0.11+10' + (platform === 'darwin' ? '.jdk/Contents/Home' : ''), license: 'GPL-2.0 WITH Classpath-exception-2.0; included legal notices' };
16
+ const java = catalogArtifact(jdk[1]);
18
17
  let ghidra = ghidraArchive;
19
18
  if (platform === 'darwin') {
20
19
  const major = Number(kernel.split('.')[0]);
21
20
  if (major < 23)
22
21
  fail('configuration', 'Managed macOS runtimes require macOS 14 or newer.');
23
22
  const tag = arch === 'x64' ? 'sonoma' : major >= 25 ? 'arm64_tahoe' : major >= 24 ? 'arm64_sequoia' : 'arm64_sonoma', hash = bottles[tag];
24
- ghidra = { name: 'ghidra-12.1.2-' + tag, url: 'https://ghcr.io/v2/homebrew/core/ghidra/blobs/sha256:' + hash, sha256: hash, format: 'tgz', root: 'ghidra/12.1.2/libexec', license: ghidraArchive.license };
23
+ ghidra = catalogArtifact(hash);
25
24
  }
26
25
  return { schema: 1, ghidraVersion: '12.1.2', javaVersion: '21.0.11+10', platform, architecture: arch, ghidra, java };
27
26
  }