@eyeauras/insight-cli 0.2.0 → 0.2.2
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.
- package/.cli-package-build.json +1 -1
- package/README.md +25 -0
- package/SKILL.md +38 -54
- package/dist/src/binary.d.ts +3 -0
- package/dist/src/binary.js +74 -0
- package/dist/src/capture.d.ts +3 -0
- package/dist/src/capture.js +220 -0
- package/dist/src/cli.js +57 -12
- package/dist/src/contexts.d.ts +5 -0
- package/dist/src/contexts.js +42 -16
- package/dist/src/debugger-caller.d.ts +17 -0
- package/dist/src/debugger-caller.js +129 -0
- package/dist/src/debugger-launch.d.ts +2 -0
- package/dist/src/debugger-launch.js +17 -0
- package/dist/src/debugger-results.d.ts +1 -0
- package/dist/src/debugger-results.js +8 -0
- package/dist/src/debugger-supervisor.js +56 -13
- package/dist/src/debugger.js +16 -7
- package/dist/src/die.d.ts +12 -0
- package/dist/src/die.js +127 -0
- package/dist/src/dnspy-runtime.d.ts +8 -0
- package/dist/src/dnspy-runtime.js +46 -0
- package/dist/src/dnspy.d.ts +22 -0
- package/dist/src/dnspy.js +160 -0
- package/dist/src/dotnet-diagnostics.d.ts +13 -0
- package/dist/src/dotnet-diagnostics.js +101 -0
- package/dist/src/frida-worker.d.ts +1 -0
- package/dist/src/frida-worker.js +125 -0
- package/dist/src/frida.d.ts +16 -0
- package/dist/src/frida.js +125 -0
- package/dist/src/ghidra-debugger-runtime.d.ts +7 -0
- package/dist/src/ghidra-debugger-runtime.js +31 -0
- package/dist/src/ghidra-processes.d.ts +6 -0
- package/dist/src/ghidra-processes.js +121 -0
- package/dist/src/ghidra.js +6 -6
- package/dist/src/ilspy.d.ts +7 -0
- package/dist/src/ilspy.js +122 -0
- package/dist/src/lldb.d.ts +10 -0
- package/dist/src/lldb.js +99 -0
- package/dist/src/llvm.d.ts +6 -0
- package/dist/src/llvm.js +133 -0
- package/dist/src/managed-heap.d.ts +4 -0
- package/dist/src/managed-heap.js +73 -0
- package/dist/src/managed-metadata.d.ts +11 -0
- package/dist/src/managed-metadata.js +66 -0
- package/dist/src/mitmproxy.d.ts +55 -0
- package/dist/src/mitmproxy.js +172 -0
- package/dist/src/native-inputs.d.ts +3 -2
- package/dist/src/native-inputs.js +9 -4
- package/dist/src/package-version.d.ts +1 -0
- package/dist/src/package-version.js +3 -0
- package/dist/src/procmon-config.d.ts +2 -0
- package/dist/src/procmon-config.js +15 -0
- package/dist/src/procmon-events.d.ts +13 -0
- package/dist/src/procmon-events.js +82 -0
- package/dist/src/procmon.d.ts +4 -0
- package/dist/src/procmon.js +107 -0
- package/dist/src/research.d.ts +11 -2
- package/dist/src/research.js +5 -3
- package/dist/src/runtime-catalog.d.ts +5 -10
- package/dist/src/runtime-catalog.js +4 -5
- package/dist/src/runtime-manager.d.ts +27 -3
- package/dist/src/runtime-manager.js +100 -159
- package/dist/src/runtime-selection.js +21 -4
- package/dist/src/server.d.ts +13 -0
- package/dist/src/server.js +21 -45
- package/dist/src/sevenzip.d.ts +15 -0
- package/dist/src/sevenzip.js +119 -0
- package/dist/src/strace.d.ts +10 -0
- package/dist/src/strace.js +71 -0
- package/dist/src/text-window.d.ts +11 -0
- package/dist/src/text-window.js +6 -0
- package/dist/src/tool-runtime/archives.d.ts +10 -0
- package/dist/src/{runtime-archives.js → tool-runtime/archives.js} +91 -24
- package/dist/src/tool-runtime/catalog.d.ts +3 -0
- package/dist/src/tool-runtime/catalog.js +13 -0
- package/dist/src/tool-runtime/commands.d.ts +9 -0
- package/dist/src/tool-runtime/commands.js +39 -0
- package/dist/src/tool-runtime/deadline.d.ts +11 -0
- package/dist/src/tool-runtime/deadline.js +32 -0
- package/dist/src/tool-runtime/definition.d.ts +73 -0
- package/dist/src/tool-runtime/definition.js +49 -0
- package/dist/src/tool-runtime/dotnet.d.ts +4 -0
- package/dist/src/tool-runtime/dotnet.js +22 -0
- package/dist/src/tool-runtime/identity.d.ts +6 -0
- package/dist/src/tool-runtime/identity.js +50 -0
- package/dist/src/tool-runtime/installer.d.ts +101 -0
- package/dist/src/tool-runtime/installer.js +180 -0
- package/dist/src/tool-runtime/java-arguments.d.ts +6 -0
- package/dist/src/tool-runtime/java-arguments.js +44 -0
- package/dist/src/tool-runtime/launch-worker.d.ts +1 -0
- package/dist/src/tool-runtime/launch-worker.js +58 -0
- package/dist/src/tool-runtime/run.d.ts +51 -0
- package/dist/src/tool-runtime/run.js +159 -0
- package/dist/src/tool-runtime/store.d.ts +15 -0
- package/dist/src/tool-runtime/store.js +219 -0
- package/dist/src/tool-runtime/supervisor.d.ts +57 -0
- package/dist/src/tool-runtime/supervisor.js +269 -0
- package/dist/src/tool-runtime/windows-job.d.ts +22 -0
- package/dist/src/tool-runtime/windows-job.js +43 -0
- package/dist/src/toolbox.d.ts +84 -0
- package/dist/src/toolbox.js +35 -0
- package/dist/src/tshark.d.ts +23 -0
- package/dist/src/tshark.js +174 -0
- package/dist/src/windbg.d.ts +14 -0
- package/dist/src/windbg.js +119 -0
- package/dist/src/workspace.d.ts +1 -0
- package/dist/src/workspace.js +6 -0
- package/package.json +5 -4
- package/references/agent-execution.md +36 -0
- package/references/agent-setup.md +61 -0
- package/references/artifacts.md +5 -0
- package/references/debugger.md +22 -0
- package/references/ilspy.md +33 -0
- package/references/managed-runtime.md +53 -7
- package/references/native/InsightPythonWheels.java +283 -2
- package/references/native/InsightTraceState.java +28 -13
- package/references/native-workflows.md +10 -0
- package/references/setup.md +2 -1
- package/runtime/managed/insight-heap/Azure.Core.dll +0 -0
- package/runtime/managed/insight-heap/Azure.Identity.dll +0 -0
- package/runtime/managed/insight-heap/Insight.Heap.csproj +1 -0
- package/runtime/managed/insight-heap/Insight.Heap.deps.json +391 -0
- package/runtime/managed/insight-heap/Insight.Heap.dll +0 -0
- package/runtime/managed/insight-heap/Insight.Heap.runtimeconfig.json +13 -0
- package/runtime/managed/insight-heap/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Diagnostics.NETCore.Client.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Diagnostics.Runtime.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Options.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Primitives.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Identity.Client.Extensions.Msal.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Identity.Client.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.IdentityModel.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Security.AntiSSRF.dll +0 -0
- package/runtime/managed/insight-heap/NuGet.Config +1 -0
- package/runtime/managed/insight-heap/Program.cs +20 -0
- package/runtime/managed/insight-heap/README.md +16 -0
- package/runtime/managed/insight-heap/System.ClientModel.dll +0 -0
- package/runtime/managed/insight-heap/System.Memory.Data.dll +0 -0
- package/runtime/managed/insight-heap/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/runtime/managed/insight-heap/dependencies.json +436 -0
- package/runtime/managed/insight-heap/notices/Azure.Core-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Azure.Identity-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.NETCore.Client-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.Runtime-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client.Extensions.Msal-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.IdentityModel.Abstractions-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Security.AntiSSRF-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/System.ClientModel-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/System.Memory.Data-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/System.Memory.Data-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-LICENSE.TXT +23 -0
- package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-THIRD-PARTY-NOTICES.TXT +309 -0
- package/runtime/managed/insight-heap/packages.lock.json +165 -0
- package/runtime/managed/insight-heap/provenance.json +146 -0
- package/runtime/managed/insight-heap/runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/runtime/managed/insight-managed/Insight.Managed.csproj +4 -0
- package/runtime/managed/insight-managed/Insight.Managed.deps.json +41 -0
- package/runtime/managed/insight-managed/Insight.Managed.dll +0 -0
- package/runtime/managed/insight-managed/Insight.Managed.runtimeconfig.json +13 -0
- package/runtime/managed/insight-managed/LICENSE.dnlib.txt +20 -0
- package/runtime/managed/insight-managed/NuGet.Config +1 -0
- package/runtime/managed/insight-managed/Program.cs +31 -0
- package/runtime/managed/insight-managed/README.md +16 -0
- package/runtime/managed/insight-managed/dnlib.dll +0 -0
- package/runtime/managed/insight-managed/packages.lock.json +13 -0
- package/runtime/managed/insight-managed/provenance.json +40 -0
- package/runtime/native/binary/README.md +22 -0
- package/runtime/native/binary/dependencies.json +166 -0
- package/runtime/native/binary/helper.cpp +44 -0
- package/runtime/native/binary/insight-binary-darwin-arm64 +0 -0
- package/runtime/native/binary/notices/Catch2-3.12.0--Catch2-3.12.0__LICENSE.txt +23 -0
- package/runtime/native/binary/notices/LIEF-LICENSE.txt +202 -0
- package/runtime/native/binary/notices/LIEF-attribution.txt +37 -0
- package/runtime/native/binary/notices/Melkor_ELF_Fuzzer-ac2495b--elf_fuzzer-master__LICENSE.txt +674 -0
- package/runtime/native/binary/notices/expected-1.3.1--expected-1.3.1__COPYING +121 -0
- package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__AUTHORS +3 -0
- package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__LICENSE +202 -0
- package/runtime/native/binary/notices/json-LICENSE.MIT +21 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--LICENSE +553 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--framework__LICENSE +553 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__LICENSE +552 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__framework__LICENSE +553 -0
- package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--LICENSE +26 -0
- package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--ext__robin_map__LICENSE +21 -0
- package/runtime/native/binary/notices/span-LICENSE_1_0.txt +23 -0
- package/runtime/native/binary/notices/span-attribution.txt +11 -0
- package/runtime/native/binary/notices/spdlog-1.17.0--spdlog-1.17.0__LICENSE +25 -0
- package/runtime/native/binary/notices/utfcpp-4.0.9--utfcpp-4.0.9__LICENSE +23 -0
- package/runtime/native/binary/provenance.json +48 -0
- package/runtime/native/child-deadline-linux-x64 +0 -0
- package/runtime/native/child-deadline-linux.c +24 -0
- package/runtime/native/child-deadline-linux.provenance.json +17 -0
- package/runtime/native/deadline-alarm-darwin-universal.dylib +0 -0
- package/runtime/native/deadline-alarm.c +33 -0
- package/runtime/native/deadline-alarm.provenance.json +22 -0
- package/runtime/native/deadline-exec-darwin-arm64 +0 -0
- package/runtime/native/deadline-exec.c +24 -0
- package/runtime/native/deadline-exec.provenance.json +17 -0
- package/runtime/native/dnspy-extension/Bridge.cs +58 -0
- package/runtime/native/dnspy-extension/Insight.DnSpy.csproj +13 -0
- package/runtime/native/dnspy-extension/Insight.DnSpy.x.dll +0 -0
- package/runtime/native/dnspy-extension/NuGet.Config +1 -0
- package/runtime/native/dnspy-extension/UNICODE-LOADER.md +26 -0
- package/runtime/native/dnspy-extension/packages.lock.json +6 -0
- package/runtime/native/dnspy-extension/provenance.json +27 -0
- package/runtime/native/dnspy-extension/upstream-public-build.snk +0 -0
- package/runtime/native/dnspy-extension/vendor-files.json +4341 -0
- package/runtime/native/file-version.ps1 +7 -0
- package/runtime/native/insight-registry-win-x64.dll +0 -0
- package/runtime/native/mitmproxy/bridge.py +180 -0
- package/runtime/native/mitmproxy/notices.json +476 -0
- package/runtime/native/sources/detours-LICENSE.md +23 -0
- package/runtime/native/sources/detours-e4bfd6b.tar.gz +0 -0
- package/runtime/native/sources/detours-provenance.json +10 -0
- package/runtime/native/tshark-layout.json +2247 -0
- package/runtime/native/windows-job/DirectoryAlias.cs +24 -0
- package/runtime/native/windows-job/Insight.WindowsJob.csproj +1 -0
- package/runtime/native/windows-job/Insight.WindowsJob.dll +0 -0
- package/runtime/native/windows-job/NuGet.Config +1 -0
- package/runtime/native/windows-job/OwnedJob.cs +79 -0
- package/runtime/native/windows-job/RegistryRedirect.cs +45 -0
- package/runtime/native/windows-job/packages.lock.json +21 -0
- package/runtime/native/windows-job/provenance.json +16 -0
- package/runtime/native/windows-job/windows-job.ps1 +8 -0
- package/runtime/native/windows-registry.c +21 -0
- package/runtime/native/windows-registry.def +3 -0
- package/runtime/native/windows-registry.provenance.json +14 -0
- package/runtime/notices/diagnostics-10.0.750501.txt +23 -0
- package/runtime/tool-catalog.json +290 -0
- package/runtime/toolbox.json +1401 -0
- package/skill-bundle/insight-artifacts/SKILL.md +30 -0
- package/skill-bundle/insight-artifacts/references/agent-execution.md +36 -0
- package/skill-bundle/insight-artifacts/references/artifacts.md +52 -0
- package/skill-bundle/insight-binary/SKILL.md +46 -0
- package/skill-bundle/insight-binary/references/agent-execution.md +36 -0
- package/skill-bundle/insight-capture/SKILL.md +56 -0
- package/skill-bundle/insight-capture/references/agent-execution.md +36 -0
- package/skill-bundle/insight-cli/SKILL.md +42 -0
- package/skill-bundle/insight-cli/references/agent-execution.md +36 -0
- package/skill-bundle/insight-cli/references/agent-setup.md +61 -0
- package/skill-bundle/insight-die/SKILL.md +49 -0
- package/skill-bundle/insight-die/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dnspy/SKILL.md +65 -0
- package/skill-bundle/insight-dnspy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-dump/SKILL.md +46 -0
- package/skill-bundle/insight-dotnet-dump/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-stack/SKILL.md +39 -0
- package/skill-bundle/insight-dotnet-stack/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-trace/SKILL.md +45 -0
- package/skill-bundle/insight-dotnet-trace/references/agent-execution.md +36 -0
- package/skill-bundle/insight-frida/SKILL.md +67 -0
- package/skill-bundle/insight-frida/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ghidra/SKILL.md +91 -0
- package/skill-bundle/insight-ghidra/references/administration.md +34 -0
- package/skill-bundle/insight-ghidra/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ghidra/references/archive.md +32 -0
- package/skill-bundle/insight-ghidra/references/artifacts.md +52 -0
- package/skill-bundle/insight-ghidra/references/debugger.md +62 -0
- package/skill-bundle/insight-ghidra/references/extensions-and-sync.md +124 -0
- package/skill-bundle/insight-ghidra/references/managed-runtime.md +162 -0
- package/skill-bundle/insight-ghidra/references/native-workflows.md +122 -0
- package/skill-bundle/insight-ghidra/references/query-semantics.md +96 -0
- package/skill-bundle/insight-ghidra/references/recovery.md +53 -0
- package/skill-bundle/insight-ghidra/references/research.md +101 -0
- package/skill-bundle/insight-ghidra/references/setup.md +50 -0
- package/skill-bundle/insight-ilspy/SKILL.md +45 -0
- package/skill-bundle/insight-ilspy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ilspy/references/ilspy.md +33 -0
- package/skill-bundle/insight-interop/SKILL.md +54 -0
- package/skill-bundle/insight-interop/references/agent-execution.md +36 -0
- package/skill-bundle/insight-lldb/SKILL.md +54 -0
- package/skill-bundle/insight-lldb/references/agent-execution.md +36 -0
- package/skill-bundle/insight-llvm/SKILL.md +56 -0
- package/skill-bundle/insight-llvm/references/agent-execution.md +36 -0
- package/skill-bundle/insight-managed-heap/SKILL.md +43 -0
- package/skill-bundle/insight-managed-heap/references/agent-execution.md +36 -0
- package/skill-bundle/insight-managed-metadata/SKILL.md +52 -0
- package/skill-bundle/insight-managed-metadata/references/agent-execution.md +36 -0
- package/skill-bundle/insight-mitmproxy/SKILL.md +62 -0
- package/skill-bundle/insight-mitmproxy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-overview/SKILL.md +79 -0
- package/skill-bundle/insight-overview/references/agent-execution.md +36 -0
- package/skill-bundle/insight-procmon/SKILL.md +49 -0
- package/skill-bundle/insight-procmon/references/agent-execution.md +36 -0
- package/skill-bundle/insight-re/SKILL.md +121 -0
- package/skill-bundle/insight-re/references/agent-execution.md +36 -0
- package/skill-bundle/insight-re/references/artifacts.md +52 -0
- package/skill-bundle/insight-re/references/recovery.md +53 -0
- package/skill-bundle/insight-sevenzip/SKILL.md +42 -0
- package/skill-bundle/insight-sevenzip/references/agent-execution.md +36 -0
- package/skill-bundle/insight-strace/SKILL.md +46 -0
- package/skill-bundle/insight-strace/references/agent-execution.md +36 -0
- package/skill-bundle/insight-tshark/SKILL.md +49 -0
- package/skill-bundle/insight-tshark/references/agent-execution.md +36 -0
- package/skill-bundle/insight-windbg/SKILL.md +46 -0
- package/skill-bundle/insight-windbg/references/agent-execution.md +36 -0
- package/skill-bundle/manifest.json +32 -0
- package/skills/insight-artifacts/SKILL.md +30 -0
- package/skills/insight-artifacts/references/agent-execution.md +36 -0
- package/skills/insight-artifacts/references/artifacts.md +52 -0
- package/skills/insight-binary/SKILL.md +46 -0
- package/skills/insight-binary/references/agent-execution.md +36 -0
- package/skills/insight-capture/SKILL.md +56 -0
- package/skills/insight-capture/references/agent-execution.md +36 -0
- package/skills/insight-die/SKILL.md +49 -0
- package/skills/insight-die/references/agent-execution.md +36 -0
- package/skills/insight-dnspy/SKILL.md +65 -0
- package/skills/insight-dnspy/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-dump/SKILL.md +46 -0
- package/skills/insight-dotnet-dump/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-stack/SKILL.md +39 -0
- package/skills/insight-dotnet-stack/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-trace/SKILL.md +45 -0
- package/skills/insight-dotnet-trace/references/agent-execution.md +36 -0
- package/skills/insight-frida/SKILL.md +67 -0
- package/skills/insight-frida/references/agent-execution.md +36 -0
- package/skills/insight-ghidra/SKILL.md +91 -0
- package/skills/insight-ghidra/references/administration.md +34 -0
- package/skills/insight-ghidra/references/agent-execution.md +36 -0
- package/skills/insight-ghidra/references/archive.md +32 -0
- package/skills/insight-ghidra/references/artifacts.md +52 -0
- package/skills/insight-ghidra/references/debugger.md +62 -0
- package/skills/insight-ghidra/references/extensions-and-sync.md +124 -0
- package/skills/insight-ghidra/references/managed-runtime.md +162 -0
- package/skills/insight-ghidra/references/native-workflows.md +122 -0
- package/skills/insight-ghidra/references/query-semantics.md +96 -0
- package/skills/insight-ghidra/references/recovery.md +53 -0
- package/skills/insight-ghidra/references/research.md +101 -0
- package/skills/insight-ghidra/references/setup.md +50 -0
- package/skills/insight-ilspy/SKILL.md +45 -0
- package/skills/insight-ilspy/references/agent-execution.md +36 -0
- package/skills/insight-ilspy/references/ilspy.md +33 -0
- package/skills/insight-interop/SKILL.md +54 -0
- package/skills/insight-interop/references/agent-execution.md +36 -0
- package/skills/insight-lldb/SKILL.md +54 -0
- package/skills/insight-lldb/references/agent-execution.md +36 -0
- package/skills/insight-llvm/SKILL.md +56 -0
- package/skills/insight-llvm/references/agent-execution.md +36 -0
- package/skills/insight-managed-heap/SKILL.md +43 -0
- package/skills/insight-managed-heap/references/agent-execution.md +36 -0
- package/skills/insight-managed-metadata/SKILL.md +52 -0
- package/skills/insight-managed-metadata/references/agent-execution.md +36 -0
- package/skills/insight-mitmproxy/SKILL.md +62 -0
- package/skills/insight-mitmproxy/references/agent-execution.md +36 -0
- package/skills/insight-overview/SKILL.md +79 -0
- package/skills/insight-overview/references/agent-execution.md +36 -0
- package/skills/insight-procmon/SKILL.md +49 -0
- package/skills/insight-procmon/references/agent-execution.md +36 -0
- package/skills/insight-re/SKILL.md +22 -9
- package/skills/insight-re/references/agent-execution.md +36 -0
- package/skills/insight-re/references/artifacts.md +52 -0
- package/skills/insight-re/references/recovery.md +53 -0
- package/skills/insight-sevenzip/SKILL.md +42 -0
- package/skills/insight-sevenzip/references/agent-execution.md +36 -0
- package/skills/insight-strace/SKILL.md +46 -0
- package/skills/insight-strace/references/agent-execution.md +36 -0
- package/skills/insight-tshark/SKILL.md +49 -0
- package/skills/insight-tshark/references/agent-execution.md +36 -0
- package/skills/insight-windbg/SKILL.md +46 -0
- package/skills/insight-windbg/references/agent-execution.md +36 -0
- package/dist/src/runtime-archives.d.ts +0 -5
package/.cli-package-build.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":1,"artifact":"
|
|
1
|
+
{"version":1,"artifact":"046be98b4da24b7ec169f1c82195fe9285221d9917d4bec0e4635e9b91febaa3"}
|
package/README.md
CHANGED
|
@@ -19,8 +19,31 @@ The pinned Factory IPC runtime is a normal npm dependency fetched from an immuta
|
|
|
19
19
|
GitHub tarball URL; installation therefore needs npm registry and GitHub access.
|
|
20
20
|
Use `insight-cli ghidra install` to deliver the pinned Ghidra/JDK/native/server runtime.
|
|
21
21
|
External Ghidra launchers and Java paths are also supported.
|
|
22
|
+
`insight-cli ilspy install` delivers ILSpy and its private .NET runtime for managed-code
|
|
23
|
+
research. Tool downloads use pinned assets retained in our GitHub Releases.
|
|
24
|
+
Use `insight-cli tools processes` to inspect owned executions across tools.
|
|
22
25
|
Help, skill discovery and saving ordinary files do not need Ghidra or Java.
|
|
23
26
|
|
|
27
|
+
Downloading a tool does not expose it in an agent's tool list. Connect the packaged skills
|
|
28
|
+
to your agent host, or explicitly give the agent the path returned by `insight-cli skill
|
|
29
|
+
insight-re --json`. See [agent setup](references/agent-setup.md) for tested project-local
|
|
30
|
+
Codex setup and a practical usability check. Installation leaves agent settings unchanged.
|
|
31
|
+
|
|
32
|
+
## Discover the toolbox
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
insight-cli tools list --json
|
|
36
|
+
insight-cli tools show die --json
|
|
37
|
+
insight-cli skill insight-die --json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The catalog describes the adapters and their packaged skills before any runtime is downloaded.
|
|
41
|
+
Use each tool's `status` to check the selected profile, then follow its skill and generated help.
|
|
42
|
+
The toolbox includes Ghidra, ILSpy, 7-Zip, LLVM utilities, DiE, LLDB, Frida, WinDbg, strace and .NET dump/stack/trace; platform
|
|
43
|
+
and capability limits are explicit per tool. A partial classification or a failed native process
|
|
44
|
+
is not a complete finding. Preserve useful output in ordinary project files and checkpoint it
|
|
45
|
+
with `artifacts save` when useful. Existing project RE instructions retain precedence.
|
|
46
|
+
|
|
24
47
|
## Start
|
|
25
48
|
|
|
26
49
|
```sh
|
|
@@ -59,3 +82,5 @@ License: MIT. The bundled GhidraMCP bridge has its own Apache-2.0 license and no
|
|
|
59
82
|
|
|
60
83
|
Runtime management, local archives and external paths: [managed runtime](references/managed-runtime.md).
|
|
61
84
|
The host debugger and OS permissions are checked separately by `ghidra doctor`.
|
|
85
|
+
|
|
86
|
+
Static .NET commands and ordinary output files: [ILSpy](references/ilspy.md).
|
package/SKILL.md
CHANGED
|
@@ -1,58 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: insight-cli
|
|
3
|
-
description:
|
|
3
|
+
description: Choose and prepare reverse-engineering capabilities from the insight-cli toolbox for binary, managed-code and runtime investigations. Use to discover the appropriate tool or its packaged skill before installing native runtimes.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# insight-cli 0.2.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
For project files, program export/import and configured-server administration, read
|
|
45
|
-
[administration](references/administration.md). These operations preserve separate research views;
|
|
46
|
-
their external effects do not participate in program merge.
|
|
47
|
-
|
|
48
|
-
For owned GUI execution, CPU state, breakpoints and retained traces, read
|
|
49
|
-
[debugger](references/debugger.md). Execution side effects remain separate from program publication.
|
|
50
|
-
|
|
51
|
-
For explicit external documentation exchange and retained submission outcomes, read
|
|
52
|
-
[archive](references/archive.md).
|
|
53
|
-
|
|
54
|
-
For selected native SDK extensions (VT, DB differences, byte/assembly edits, formats, GDT,
|
|
55
|
-
FID/BSim, namespaces and typed IR), read [native workflows](references/native-workflows.md).
|
|
56
|
-
|
|
57
|
-
For managed SDK extension modules, actual language/analyzer/plugin discovery and opt-in
|
|
58
|
-
automatic synchronization, read [extensions and sync](references/extensions-and-sync.md).
|
|
6
|
+
# insight-cli 0.2.2
|
|
7
|
+
|
|
8
|
+
If local help/status reports AppData or IPC access denied, retry that **read-only probe**
|
|
9
|
+
with the agent host's normal permission escalation, then use that route for later authorized
|
|
10
|
+
CLI calls too. An explicit **no command was sent** denial is known undispatched and can be
|
|
11
|
+
retried through that route. Keep HOME, profile and owner state; see
|
|
12
|
+
[host execution permissions](references/agent-execution.md). A lost mutation reply needs
|
|
13
|
+
request/status recovery, never blind retry.
|
|
14
|
+
|
|
15
|
+
Read the project's RE instructions and existing findings first. They own tool choices,
|
|
16
|
+
evidence layout, formats and source of truth. These skills fill the remaining gaps.
|
|
17
|
+
|
|
18
|
+
1. Run `insight-cli tools list --json` to discover the capabilities shipped in this version.
|
|
19
|
+
The catalog works before profile configuration, downloads or IPC startup. A downloaded
|
|
20
|
+
runtime is not needed to discover what a tool does.
|
|
21
|
+
2. Use `insight-cli tools show <tool> --json` for tasks, supported inputs/platforms,
|
|
22
|
+
dependencies and its skill path. Read that skill before preparing or using the tool.
|
|
23
|
+
3. Select a profile for execution. Run the selected application's `status` and generated
|
|
24
|
+
`--help`. `install` prepares its private runtime; archives/offline and external paths
|
|
25
|
+
are tool-specific and described in its skill. Update permission is required for tool
|
|
26
|
+
preparation/execution and saved changes: `insight-cli permissions grant Update`.
|
|
27
|
+
4. Answer the question with focused queries and ordinary project files. Follow results to
|
|
28
|
+
useful detail; a large raw dump is not an interpretation. External tools remain welcome.
|
|
29
|
+
5. Preserve completed files with `insight-cli artifacts save <path> --json` when a retained
|
|
30
|
+
checkpoint helps. For several agents sharing Ghidra analysis, use separate sessions,
|
|
31
|
+
then explicit merge/refresh as described by its skill.
|
|
32
|
+
|
|
33
|
+
`insight-cli skill` locates this entry point. `skill insight-re` gives investigation and
|
|
34
|
+
multi-agent guidance; `skill insight-ghidra`, `skill insight-ilspy` and
|
|
35
|
+
`skill insight-artifacts` locate the relevant instructions. Skills ship with the CLI;
|
|
36
|
+
installing npm binaries does not register them in an agent host. See
|
|
37
|
+
[agent connection](references/agent-setup.md) for current setup and access requirements.
|
|
38
|
+
|
|
39
|
+
Use generated help as the syntax authority. Catalog metadata describes shipped capabilities;
|
|
40
|
+
profile runtime readiness comes from the selected tool's `status`. Unavailable profile/IPC
|
|
41
|
+
access means execution readiness is unknown. Preserve work and diagnose access before trying
|
|
42
|
+
again; stopping a shared owner does not grant a denied agent access to it.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { command, Permission, CliError } from '@eyeauras/cli-factory';
|
|
2
|
+
import { join, resolve, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { mkdir, writeFile, copyFile, readFile } from 'node:fs/promises';
|
|
5
|
+
import { constants } from 'node:fs';
|
|
6
|
+
import { release } from 'node:os';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { runTool } from './tool-runtime/run.js';
|
|
9
|
+
import { atomicWrite } from './tool-runtime/store.js';
|
|
10
|
+
import { fileSha256 } from './tool-runtime/archives.js';
|
|
11
|
+
import { fail, text, id } from './model.js';
|
|
12
|
+
import { number } from './research.js';
|
|
13
|
+
const helper = fileURLToPath(new URL('../../runtime/native/binary/insight-binary-darwin-arm64', import.meta.url));
|
|
14
|
+
export function binaryCommands(workspace) {
|
|
15
|
+
const run = (mode) => command(mode + ' [input]', mode === 'query' ? 'Inspect bounded PE, ELF or thin Mach-O metadata without executing the input' : 'Change one expected PE subsystem field in a new copy and independently read it back', async ({ args, options: o }, c) => {
|
|
16
|
+
if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
|
|
17
|
+
fail('unsupported', 'The packaged LIEF facade is currently verified on macOS14+ ARM64; input formats are PE, ELF and thin Mach-O.');
|
|
18
|
+
if (Boolean(args.input) === Boolean(o.target))
|
|
19
|
+
fail('invalid', 'Supply one binary input or --target.');
|
|
20
|
+
const view = mode === 'query' ? text(o.view ?? 'overview', 16) : undefined;
|
|
21
|
+
if (view && !['overview', 'sections', 'libraries', 'imports', 'exports'].includes(view))
|
|
22
|
+
fail('invalid', 'Use overview, sections, libraries, imports or exports.');
|
|
23
|
+
const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target));
|
|
24
|
+
if (target.input.size > 64 * 1024 ** 2)
|
|
25
|
+
fail('limit', 'Structured binary input exceeds 64 MiB.');
|
|
26
|
+
const input = await w.artifacts.verify(target.input);
|
|
27
|
+
const directory = join(c.appArguments.AppDataDirectory, 'runtime/binary/queries', randomUUID()), plan = join(directory, 'plan.json'), edited = join(directory, 'edited.exe');
|
|
28
|
+
let edit;
|
|
29
|
+
if (mode === 'edit-subsystem') {
|
|
30
|
+
if (!o.output)
|
|
31
|
+
fail('invalid', 'Copy-only editing requires --output FILE.');
|
|
32
|
+
const values = { gui: 2, console: 3 }, expected = values[text(o.expectSubsystem, 16)], value = values[text(o.subsystem, 16)];
|
|
33
|
+
if (!expected || !value || expected === value)
|
|
34
|
+
fail('invalid', 'Choose a different gui/console subsystem and an explicit --expect-subsystem.');
|
|
35
|
+
edit = { expectedSubsystem: expected, subsystem: value, output: edited };
|
|
36
|
+
}
|
|
37
|
+
await atomicWrite(plan, { schema: 1, mode, input, view, filter: o.filter === undefined ? undefined : text(o.filter, 4096), limit, offset, ...edit });
|
|
38
|
+
const result = await runTool(c, { tool: 'binary', role: mode, executable: helper, arguments: [plan], timeoutMs: 60000, maxOutputBytes: 8 * 1024 ** 2, nativeDeadline: true, target: target.id, metadata: { view, helperSha256: await fileSha256(helper) } });
|
|
39
|
+
let observation;
|
|
40
|
+
try {
|
|
41
|
+
observation = JSON.parse(result.stdout);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new CliError('Binary parser did not return complete bounded JSON.', { code: 'tool.partial', result: { process: result.process, diagnostics: result.diagnostics } });
|
|
45
|
+
}
|
|
46
|
+
if (!['completed', 'partial'].includes(observation?.state) || typeof observation.complete !== 'boolean')
|
|
47
|
+
fail('partial', 'Binary query receipt was not verified.', { process: result.process, diagnostics: result.diagnostics });
|
|
48
|
+
if (await fileSha256(input) !== target.binarySha256)
|
|
49
|
+
fail('binding', 'Immutable binary changed during inspection.');
|
|
50
|
+
const warnings = result.stderr.trim(), value = { ...observation, ...(warnings ? { state: 'partial', complete: false, reason: 'native_parser_diagnostics', warnings: warnings.slice(0, 4096), warningsTruncated: warnings.length > 4096 } : {}), target: target.id, inputSha256: target.binarySha256, process: result.process, elapsedMs: result.elapsedMs, diagnostics: result.diagnostics };
|
|
51
|
+
if (mode === 'edit-subsystem') {
|
|
52
|
+
if (!value.complete)
|
|
53
|
+
fail('partial', 'Native parser diagnostics prevent accepting the copied edit.', value);
|
|
54
|
+
const before = await readFile(input), after = await readFile(edited), at = Number(BigInt(observation.fieldOffset));
|
|
55
|
+
if (after.length !== before.length || !Number.isSafeInteger(at) || at < 0 || at + 2 > before.length)
|
|
56
|
+
fail('binding', 'Copied PE edit did not retain its field bounds.');
|
|
57
|
+
for (let n = 0; n < before.length; n++)
|
|
58
|
+
if (n !== at && n !== at + 1 && before[n] !== after[n])
|
|
59
|
+
fail('binding', 'Copied PE edit changed bytes outside the declared field.');
|
|
60
|
+
const output = resolve(c.cwd, text(o.output, 4096));
|
|
61
|
+
await mkdir(dirname(output), { recursive: true, mode: 0o700 });
|
|
62
|
+
await copyFile(edited, output, constants.COPYFILE_EXCL);
|
|
63
|
+
return { ...value, output, outputSha256: await fileSha256(output), originalPreserved: true };
|
|
64
|
+
}
|
|
65
|
+
if (o.output) {
|
|
66
|
+
const output = resolve(c.cwd, text(o.output, 4096)), content = JSON.stringify(value, null, 2) + '\n';
|
|
67
|
+
await mkdir(dirname(output), { recursive: true, mode: 0o700 });
|
|
68
|
+
await writeFile(output, content, { flag: 'wx', mode: 0o600 });
|
|
69
|
+
return { state: value.state, complete: value.complete, reason: value.reason, target: target.id, output, bytes: Buffer.byteLength(content), process: result.process, diagnostics: result.diagnostics };
|
|
70
|
+
}
|
|
71
|
+
return value;
|
|
72
|
+
}, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable input bytes' }, { flags: '--output <file>', description: mode === 'query' ? 'Save this bounded page to a new JSON file' : 'Required new executable copy; never overwrite an existing file' }, ...(mode === 'query' ? [{ flags: '--view <kind>', description: 'overview, sections, libraries, imports or exports', defaultValue: 'overview' }, { flags: '--filter <text>', description: 'Literal metadata name substring before pagination' }, { flags: '--limit <count>', description: 'Return 1–500 rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip matching rows', defaultValue: 0 }] : [{ flags: '--expect-subsystem <kind>', description: 'Required current PE subsystem: gui or console', required: true }, { flags: '--subsystem <kind>', description: 'Required different PE subsystem: gui or console', required: true }])] });
|
|
73
|
+
return [command('binary', 'Structured binary metadata and guarded copy-only edits', [run('query'), run('edit-subsystem')])];
|
|
74
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { command, Permission, CliError } from '@eyeauras/cli-factory';
|
|
2
|
+
import { join, resolve, dirname, basename, sep } from 'node:path';
|
|
3
|
+
import { mkdir, writeFile, copyFile, chmod, open, realpath, lstat } from 'node:fs/promises';
|
|
4
|
+
import { constants } from 'node:fs';
|
|
5
|
+
import { release } from 'node:os';
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { runTool } from './tool-runtime/run.js';
|
|
8
|
+
import { atomicWrite, readJson } from './tool-runtime/store.js';
|
|
9
|
+
import { listProcesses } from './tool-runtime/supervisor.js';
|
|
10
|
+
import { fileSha256 } from './tool-runtime/archives.js';
|
|
11
|
+
import { fail, text, id } from './model.js';
|
|
12
|
+
import { number } from './research.js';
|
|
13
|
+
const sha = (b) => createHash('sha256').update(b).digest('hex');
|
|
14
|
+
const list = (v) => v === undefined ? [] : (Array.isArray(v) ? v : [v]).map(s => text(s, 4096));
|
|
15
|
+
const root = (c, request) => { if (!/^a_[a-f0-9-]{36}$/.test(request))
|
|
16
|
+
fail('invalid', 'Select a capture request returned by capture run.'); return join(c.appArguments.AppDataDirectory, 'runtime/capture', request); };
|
|
17
|
+
function relativeFile(value) { const name = text(value, 1024); if (name.includes('\\') || name.startsWith('/') || name.split('/').some(p => !p || p === '.' || p === '..') || name.toLowerCase() === 'subject')
|
|
18
|
+
fail('invalid', 'Watch paths must be ordinary relative files inside the owned working directory.'); return name; }
|
|
19
|
+
async function boundedFile(path, max = 16 * 1024 ** 2) {
|
|
20
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
21
|
+
try {
|
|
22
|
+
const before = await handle.stat();
|
|
23
|
+
if (!before.isFile() || before.size > max)
|
|
24
|
+
fail('limit', 'Selected file must be regular and within its byte bound.');
|
|
25
|
+
const chunks = [];
|
|
26
|
+
let bytes = 0;
|
|
27
|
+
for await (const chunk of handle.createReadStream({ autoClose: false })) {
|
|
28
|
+
bytes += chunk.length;
|
|
29
|
+
if (bytes > max)
|
|
30
|
+
fail('limit', 'Selected file grew beyond its capture bound.');
|
|
31
|
+
chunks.push(chunk);
|
|
32
|
+
}
|
|
33
|
+
const after = await handle.stat();
|
|
34
|
+
if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.ino !== after.ino)
|
|
35
|
+
fail('binding', 'Selected file changed while being read.');
|
|
36
|
+
return Buffer.concat(chunks);
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
await handle.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function snapshot(directory, name) {
|
|
43
|
+
const file = join(directory, name);
|
|
44
|
+
try {
|
|
45
|
+
const parent = await realpath(dirname(file)), base = await realpath(directory);
|
|
46
|
+
if (parent !== base && !parent.startsWith(base + sep))
|
|
47
|
+
return { path: name, state: 'unavailable', reason: 'parent_outside_owned_directory' };
|
|
48
|
+
const info = await lstat(file);
|
|
49
|
+
if (!info.isFile() || info.isSymbolicLink())
|
|
50
|
+
return { path: name, state: 'unavailable', reason: 'not_regular_file' };
|
|
51
|
+
const bytes = await boundedFile(file);
|
|
52
|
+
return { path: name, state: 'present', bytes: bytes.length, sha256: sha(bytes) };
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error.code === 'ENOENT')
|
|
56
|
+
return { path: name, state: 'absent' };
|
|
57
|
+
return { path: name, state: 'unavailable', reason: error.code ?? 'unreadable' };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function pageStream(value, offset, limit) { if (!value)
|
|
61
|
+
return { available: false }; const all = Buffer.from(value.base64, 'base64'), bytes = all.subarray(offset, offset + limit); return { available: true, totalBytes: value.bytes, sha256: value.sha256, offset, limit, base64: bytes.toString('base64'), text: bytes.toString('utf8'), textEncoding: 'UTF-8 preview with replacement; base64 preserves exact selected bytes', truncated: offset + limit < all.length }; }
|
|
62
|
+
function overview(receipt) { const { stdout, stderr, files, ...rest } = receipt; return { ...rest, stdout: pageStream(stdout, 0, 256), stderr: pageStream(stderr, 0, 256), declaredFiles: files.length, fileChanges: files.filter(f => f.change !== 'unchanged').map(f => ({ path: f.path, change: f.change })) }; }
|
|
63
|
+
async function exportReceipt(c, value, option) { const output = resolve(c.cwd, text(option, 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; }
|
|
64
|
+
async function receiptFor(c, w, request) { const stored = w.administration(request); if (stored.operation !== 'capture.run')
|
|
65
|
+
fail('invalid', 'Request is not an owned process capture.'); const file = join(root(c, request), 'capture.json'), receipt = await readJson(file); if (receipt && stored.state === 'applied') {
|
|
66
|
+
const result = stored.result;
|
|
67
|
+
if (result?.receiptSha256 !== await fileSha256(file))
|
|
68
|
+
fail('binding', 'Capture receipt differs from its durable outcome.');
|
|
69
|
+
validateReport(receipt);
|
|
70
|
+
if (receipt.request !== request)
|
|
71
|
+
fail('binding', 'Capture receipt has a different request identity.');
|
|
72
|
+
return receipt;
|
|
73
|
+
} return { state: stored.state === 'accepted' ? 'prepared' : 'unknown', complete: false, request, intent: stored.intent, processes: (await listProcesses(c.appArguments.AppDataDirectory, { tool: 'capture' })).filter(p => p.metadata?.request === request), directory: root(c, request), workingDirectory: join(root(c, request), 'working'), scope: 'No completed capture receipt. Inspect retained process/input/files explicitly; never rerun this request to manufacture a result.' }; }
|
|
74
|
+
function validateReport(value) {
|
|
75
|
+
const hash = (v) => typeof v === 'string' && /^[a-f0-9]{64}$/.test(v);
|
|
76
|
+
if (value?.schema !== 1 || value.kind !== 'insight-process-capture' || typeof value.complete !== 'boolean' || value.state !== (value.complete ? 'completed' : 'partial') || !hash(value.inputSha256) || !Array.isArray(value.files) || value.files.length > 32 || !value.execution || !Array.isArray(value.arguments) || value.arguments.length > 64 || value.arguments.some(a => typeof a !== 'string' || a.length > 4096) || !Array.isArray(value.inputs) || value.inputs.length > 32)
|
|
77
|
+
fail('invalid', 'Select a structured insight process capture report.');
|
|
78
|
+
if (value.execution.exitCode !== null && (!Number.isInteger(value.execution.exitCode) || value.execution.exitCode < 0 || value.execution.exitCode > 255))
|
|
79
|
+
fail('invalid', 'Invalid captured exit code.');
|
|
80
|
+
let bytes = 0;
|
|
81
|
+
for (const stream of [value.stdout, value.stderr])
|
|
82
|
+
if (stream) {
|
|
83
|
+
if (!hash(stream.sha256) || typeof stream.base64 !== 'string')
|
|
84
|
+
fail('invalid', 'Malformed capture byte stream.');
|
|
85
|
+
const raw = Buffer.from(stream.base64, 'base64');
|
|
86
|
+
if (raw.toString('base64') !== stream.base64 || raw.length !== stream.bytes || sha(raw) !== stream.sha256 || (bytes += raw.length) > 4 * 1024 ** 2)
|
|
87
|
+
fail('binding', 'Capture byte stream differs from its bounds/hash.');
|
|
88
|
+
}
|
|
89
|
+
if (value.complete && (!value.stdout || !value.stderr || value.execution.exitCode === null || value.execution.signal !== null))
|
|
90
|
+
fail('invalid', 'A complete capture requires known terminal output and exit.');
|
|
91
|
+
const seen = new Set();
|
|
92
|
+
for (const file of value.files) {
|
|
93
|
+
const name = relativeFile(file.path);
|
|
94
|
+
if (seen.has(name))
|
|
95
|
+
fail('invalid', 'Duplicate declared capture path.');
|
|
96
|
+
seen.add(name);
|
|
97
|
+
for (const observed of [file.before, file.after])
|
|
98
|
+
if (!observed || observed.path !== name || !['present', 'absent', 'unavailable'].includes(observed.state) || observed.state === 'present' && (!hash(observed.sha256) || !Number.isSafeInteger(observed.bytes) || observed.bytes < 0 || observed.bytes > 16 * 1024 ** 2))
|
|
99
|
+
fail('invalid', 'Malformed declared file observation.');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function captureCommands(workspace) {
|
|
103
|
+
const run = command('run [input]', 'Capture one explicitly selected owned native execution and declared file snapshots', async ({ args, options: o }, c) => {
|
|
104
|
+
if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
|
|
105
|
+
fail('unsupported', 'Process capture is verified on macOS14+ ARM64 thin native executables.');
|
|
106
|
+
if (Boolean(args.input) === Boolean(o.target))
|
|
107
|
+
fail('invalid', 'Supply one native program or --target.');
|
|
108
|
+
const w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target)), input = await w.artifacts.verify(target.input);
|
|
109
|
+
if (target.input.size > 64 * 1024 ** 2)
|
|
110
|
+
fail('limit', 'Owned executable exceeds 64 MiB.');
|
|
111
|
+
const header = (await boundedFile(input, 64 * 1024 ** 2)).subarray(0, 32);
|
|
112
|
+
if (header.length < 32 || header.subarray(0, 4).toString('hex') !== 'cffaedfe' || header.readUInt32LE(4) !== 0x0100000c || header.readUInt32LE(12) !== 2)
|
|
113
|
+
fail('unsupported', 'Select a thin ARM64 Mach-O executable, not a PE/ELF, script, library or universal container.');
|
|
114
|
+
const argv = list(o.arg), selected = list(o.inputFile), watched = [...new Set(list(o.watch).map(relativeFile))];
|
|
115
|
+
if (argv.length > 64 || selected.length > 32 || watched.length > 32)
|
|
116
|
+
fail('limit', 'Capture permits 64 literal arguments, 32 selected input files and 32 watch paths.');
|
|
117
|
+
const timeoutMs = number(o.timeoutSeconds ?? 10, 600, 1) * 1000, files = [];
|
|
118
|
+
let total = 0;
|
|
119
|
+
for (const option of selected) {
|
|
120
|
+
const path = resolve(c.cwd, option), name = basename(path);
|
|
121
|
+
if (name.toLowerCase() === 'subject' || files.some(f => f.name.normalize('NFD').toLowerCase() === name.normalize('NFD').toLowerCase()) || !/^[^/\\\0]+$/.test(name))
|
|
122
|
+
fail('invalid', 'Selected input basenames must be ordinary and unique.');
|
|
123
|
+
const data = await boundedFile(path);
|
|
124
|
+
if ((total += data.length) > 64 * 1024 ** 2)
|
|
125
|
+
fail('limit', 'Selected input files exceed 64 MiB.');
|
|
126
|
+
files.push({ name, sha256: sha(data), bytes: data.length, data });
|
|
127
|
+
}
|
|
128
|
+
const stdin = o.stdinFile ? await boundedFile(resolve(c.cwd, text(o.stdinFile, 4096)), 1024 ** 2) : Buffer.alloc(0);
|
|
129
|
+
if (o.output && !(o.requestId && w.administrationByCaller(id(o.requestId))))
|
|
130
|
+
try {
|
|
131
|
+
await lstat(resolve(c.cwd, text(o.output, 4096)));
|
|
132
|
+
fail('invalid', 'Capture output already exists.');
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (error.code !== 'ENOENT')
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
const intent = { target: target.id, inputSha256: target.binarySha256, arguments: argv, inputs: files.map(({ data, ...f }) => f), stdin: { sha256: sha(stdin), bytes: stdin.length }, watch: watched, timeoutMs, output: o.output ? resolve(c.cwd, text(o.output, 4096)) : undefined };
|
|
139
|
+
const reservation = w.reserveAdministration('capture.run', intent, o.requestId === undefined ? undefined : id(o.requestId)), request = reservation.request.id;
|
|
140
|
+
if (reservation.replay) {
|
|
141
|
+
const previous = await receiptFor(c, w, request);
|
|
142
|
+
if (reservation.request.state === 'applied' && 'kind' in previous) {
|
|
143
|
+
if (!previous.complete)
|
|
144
|
+
throw new CliError('Prior capture remains partial; no execution was repeated.', { code: 'tool.capture.partial', result: overview(previous) });
|
|
145
|
+
return { ...overview(previous), replayed: true };
|
|
146
|
+
}
|
|
147
|
+
throw new CliError('Capture request already exists without a verified complete outcome; no execution was repeated.', { code: 'tool.capture.unknown', result: previous });
|
|
148
|
+
}
|
|
149
|
+
const directory = root(c, request), working = join(directory, 'working'), subject = join(working, 'subject');
|
|
150
|
+
await mkdir(working, { recursive: true, mode: 0o700 });
|
|
151
|
+
await copyFile(input, subject, constants.COPYFILE_EXCL);
|
|
152
|
+
await chmod(subject, 0o700);
|
|
153
|
+
if (await fileSha256(subject) !== target.binarySha256)
|
|
154
|
+
fail('binding', 'Owned executable differs from captured input.');
|
|
155
|
+
for (const f of files)
|
|
156
|
+
await writeFile(join(working, f.name), f.data, { flag: 'wx', mode: 0o600 });
|
|
157
|
+
const before = await Promise.all(watched.map(name => snapshot(working, name)));
|
|
158
|
+
await atomicWrite(join(directory, 'intent.json'), { request, ...intent });
|
|
159
|
+
w.administrationState(request, 'running', { directory });
|
|
160
|
+
let result, failure;
|
|
161
|
+
try {
|
|
162
|
+
result = await runTool(c, { tool: 'capture', role: 'run', executable: subject, arguments: argv, cwd: working, input: stdin, timeoutMs, maxOutputBytes: 4 * 1024 ** 2, retainRawOutput: true, nativeDeadline: true, acceptedCodes: Array.from({ length: 127 }, (_, n) => n), target: target.id, metadata: { request, working, scope: 'Owned program copy; selected input copies and declared file snapshots; no shell or OS sandbox' } });
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
failure = error;
|
|
166
|
+
if (error instanceof CliError && error.result && typeof error.result === 'object' && 'stdout' in error.result)
|
|
167
|
+
result = error.result;
|
|
168
|
+
}
|
|
169
|
+
const after = await Promise.all(watched.map(name => snapshot(working, name))), unavailable = [...before, ...after].some(f => f.state === 'unavailable');
|
|
170
|
+
const stream = async (file) => { if (!file)
|
|
171
|
+
return; const b = await boundedFile(file, 4 * 1024 ** 2); return { bytes: b.length, sha256: sha(b), base64: b.toString('base64') }; };
|
|
172
|
+
const value = { schema: 1, kind: 'insight-process-capture', request, state: failure || unavailable ? 'partial' : 'completed', complete: !failure && !unavailable, ...(failure ? { reason: failure instanceof CliError ? failure.code : 'capture_failed' } : unavailable ? { reason: 'declared_file_unavailable' } : {}), target: target.id, inputSha256: target.binarySha256, timeoutMs, arguments: argv, inputs: intent.inputs, stdin: intent.stdin, stdout: await stream(result?.rawStdout), stderr: await stream(result?.rawStderr), execution: { process: result?.process, exitCode: result?.exitCode ?? null, signal: result?.signal ?? null, elapsedMs: result?.elapsedMs, diagnostics: result?.diagnostics }, files: watched.map((path, n) => { const a = before[n], b = after[n]; return { path, before: a, after: b, change: a.state === 'unavailable' || b.state === 'unavailable' ? 'unknown' : a.state === b.state && (a.state === 'absent' || a.sha256 === b.sha256) ? 'unchanged' : a.state === 'absent' ? 'created' : b.state === 'absent' ? 'deleted' : 'changed' }; }), scope: 'One owned program copy with literal argv, exact bounded stdout/stderr bytes and selected file snapshots. This is not an OS sandbox, a trace of all filesystem/network effects or proof of causality. Native deadline assumes the subject does not deliberately replace the inherited alarm. Known nonzero subject exits are captured outcomes; interrupted/overflow/unknown capture stays partial.' };
|
|
173
|
+
if (!value.stdout || !value.stderr) {
|
|
174
|
+
value.complete = false;
|
|
175
|
+
value.state = 'partial';
|
|
176
|
+
value.reason ??= 'raw_output_unavailable';
|
|
177
|
+
}
|
|
178
|
+
const path = join(directory, 'capture.json');
|
|
179
|
+
await atomicWrite(path, value);
|
|
180
|
+
w.administrationState(request, 'applied', { receipt: path, receiptSha256: await fileSha256(path), complete: value.complete });
|
|
181
|
+
const output = o.output ? await exportReceipt(c, value, o.output) : undefined;
|
|
182
|
+
if (!value.complete)
|
|
183
|
+
throw new CliError('Capture is partial; retained output/files are available and execution was not replayed.', { code: 'tool.capture.partial', result: { ...overview(value), directory, ...(output ? { output } : {}) } });
|
|
184
|
+
return { ...overview(value), directory, ...(output ? { output } : {}) };
|
|
185
|
+
}, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable native program bytes' }, { flags: '--arg <text...>', description: 'Literal subject arguments; no shell string or expansion' }, { flags: '--input-file <file...>', description: 'Copy selected regular files by unique basename into owned cwd' }, { flags: '--stdin-file <file>', description: 'Optional bounded input byte stream (up to 1 MiB)' }, { flags: '--watch <path...>', description: 'Declared relative regular files to snapshot before and after execution' }, { flags: '--timeout-seconds <seconds>', description: 'Owned execution deadline (1–600)', defaultValue: 10 }, { flags: '--output <file>', description: 'Save a new portable bounded JSON capture, including exact output base64' }, { flags: '--request-id <id>', description: 'Retrieve this exact capture intent without executing it again' }] });
|
|
186
|
+
const show = command('show <request>', 'Inspect retained capture bytes or an unresolved intent without rerunning a program', async ({ args, options: o }, c) => { const request = text(args.request, 128), value = await receiptFor(c, workspace(c), request); if (!('kind' in value))
|
|
187
|
+
return value; if (o.output)
|
|
188
|
+
return { request, complete: value.complete, output: await exportReceipt(c, value, o.output) }; const view = text(o.view ?? 'overview', 16), limit = number(o.limit ?? 50, 1000, 1), offset = number(o.offset ?? 0, 8 * 1024 ** 2); if (view === 'overview')
|
|
189
|
+
return overview(value); if (view === 'stdout' || view === 'stderr')
|
|
190
|
+
return { request, state: value.state, complete: value.complete, view, ...pageStream(value[view], offset, limit) }; if (view === 'files')
|
|
191
|
+
return { request, state: value.state, complete: value.complete, items: value.files.slice(offset, offset + limit), total: value.files.length, offset, limit, truncated: offset + limit < value.files.length }; fail('invalid', 'Use overview, stdout, stderr or files.'); }, { permission: Permission.Update, options: [{ flags: '--view <kind>', description: 'overview, stdout, stderr or files', defaultValue: 'overview' }, { flags: '--limit <count>', description: '1–1000 output bytes or file rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip output bytes or file rows', defaultValue: 0 }, { flags: '--output <file>', description: 'Export portable retained capture to a new ordinary JSON file' }] });
|
|
192
|
+
const compare = command('compare <left> <right>', 'Compare two retained capture reports without re-executing their subjects', async ({ args, options: o }, c) => {
|
|
193
|
+
async function load(path) { const file = resolve(c.cwd, text(path, 4096)), bytes = await boundedFile(file, 8 * 1024 ** 2); let value; try {
|
|
194
|
+
value = JSON.parse(bytes.toString('utf8'));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
fail('invalid', 'Capture report must be bounded JSON.');
|
|
198
|
+
} validateReport(value); return { value, sha256: sha(bytes) }; }
|
|
199
|
+
const left = await load(args.left), right = await load(args.right), a = left.value, b = right.value, changes = [], unknown = [];
|
|
200
|
+
for (const field of ['stdout', 'stderr']) {
|
|
201
|
+
if (!a[field] || !b[field])
|
|
202
|
+
unknown.push(field);
|
|
203
|
+
else if (a[field].sha256 !== b[field].sha256)
|
|
204
|
+
changes.push({ field, left: a[field].sha256, right: b[field].sha256 });
|
|
205
|
+
}
|
|
206
|
+
if (a.execution.exitCode !== b.execution.exitCode || a.execution.signal !== b.execution.signal)
|
|
207
|
+
changes.push({ field: 'exit', left: a.execution, right: b.execution });
|
|
208
|
+
const af = new Map(a.files.map(f => [f.path, f])), bf = new Map(b.files.map(f => [f.path, f]));
|
|
209
|
+
for (const name of [...new Set([...af.keys(), ...bf.keys()])].sort()) {
|
|
210
|
+
const l = af.get(name)?.after, r = bf.get(name)?.after;
|
|
211
|
+
if (!l || !r || l.state === 'unavailable' || r.state === 'unavailable')
|
|
212
|
+
unknown.push('file:' + name);
|
|
213
|
+
else if (l.state !== r.state || l.sha256 !== r.sha256)
|
|
214
|
+
changes.push({ field: 'file:' + name, left: l, right: r });
|
|
215
|
+
}
|
|
216
|
+
const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), complete = a.complete && b.complete && !unknown.length;
|
|
217
|
+
return { state: complete ? 'completed' : 'partial', complete, left: { reportSha256: left.sha256, inputSha256: a.inputSha256 }, right: { reportSha256: right.sha256, inputSha256: b.inputSha256 }, sameDeclaredIntent: JSON.stringify({ target: a.inputSha256, argv: a.arguments, inputs: a.inputs, stdin: a.stdin, watch: a.files.map(f => f.path), timeoutMs: a.timeoutMs }) === JSON.stringify({ target: b.inputSha256, argv: b.arguments, inputs: b.inputs, stdin: b.stdin, watch: b.files.map(f => f.path), timeoutMs: b.timeoutMs }), items: changes.slice(offset, offset + limit), total: changes.length, unknown, offset, limit, truncated: offset + limit < changes.length, scope: 'Literal retained field/byte comparison; no subject rerun, causal equivalence or execution-time speedup claim. Partial reports cannot prove global equality.' };
|
|
218
|
+
}, { permission: Permission.ReadOnly, options: [{ flags: '--limit <count>', description: 'Return 1–500 changed fields', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip changed fields', defaultValue: 0 }] });
|
|
219
|
+
return [command('capture', 'Own bounded native executions and compare explicitly retained observations', [run, show, compare])];
|
|
220
|
+
}
|
package/dist/src/cli.js
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
|
+
import { captureCommands } from './capture.js';
|
|
2
|
+
import { binaryCommands } from './binary.js';
|
|
3
|
+
import { skillCommand, toolboxCommands } from './toolbox.js';
|
|
4
|
+
import { listProcesses } from './tool-runtime/supervisor.js';
|
|
5
|
+
import { diagnosticsCommands } from './dotnet-diagnostics.js';
|
|
6
|
+
import { fridaCommands } from './frida.js';
|
|
7
|
+
import { mitmproxyCommands } from './mitmproxy.js';
|
|
8
|
+
import { tsharkCommands } from './tshark.js';
|
|
9
|
+
import { dnspyCommands } from './dnspy.js';
|
|
10
|
+
import { procmonCommands } from './procmon.js';
|
|
11
|
+
import { straceCommands } from './strace.js';
|
|
12
|
+
import { windbgCommands } from './windbg.js';
|
|
13
|
+
import { lldbCommands } from './lldb.js';
|
|
14
|
+
import { dieCommands } from './die.js';
|
|
15
|
+
import { llvmCommands } from './llvm.js';
|
|
16
|
+
import { sevenzipCommands } from './sevenzip.js';
|
|
17
|
+
import { ilspyCommands } from './ilspy.js';
|
|
18
|
+
import { toolProcessCommands } from './tool-runtime/commands.js';
|
|
19
|
+
import { ghidraProcessHooks } from './ghidra-processes.js';
|
|
20
|
+
import { withToolLock, toolProfileBusy } from './tool-runtime/store.js';
|
|
1
21
|
import { command, createCli, Permission, CliError, ProfileStore } from '@eyeauras/cli-factory';
|
|
2
22
|
import { join, resolve } from 'node:path';
|
|
3
23
|
import { readFile, readdir } from 'node:fs/promises';
|
|
4
24
|
import { existsSync } from 'node:fs';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
25
|
import { Workspace } from './workspace.js';
|
|
7
26
|
import { GhidraContexts } from './contexts.js';
|
|
8
27
|
import { nativeInputs } from './native-inputs.js';
|
|
@@ -28,6 +47,7 @@ import { Extensions, extensionCommands, extensionState, extensionInventoryComman
|
|
|
28
47
|
import { Synchronization, synchronizationCommands } from './sync-policy.js';
|
|
29
48
|
import { artifactsCommands } from './saved-materials.js';
|
|
30
49
|
import { RuntimeManager, runtimeCommands, runtimeProcesses } from './runtime-manager.js';
|
|
50
|
+
import { packageVersion } from './package-version.js';
|
|
31
51
|
import { runtimeSelection } from './runtime-selection.js';
|
|
32
52
|
const bindingFields = ['java', 'ghidraHome', 'mcpJar', 'mcpJarSha256', 'server', 'repository', 'readerUser', 'publisherUser', 'maxContexts', 'debuggerPython', 'windbgDir', 'archiveUrl'];
|
|
33
53
|
class Owner {
|
|
@@ -53,7 +73,7 @@ class Owner {
|
|
|
53
73
|
current.workspace.close();
|
|
54
74
|
this.profiles.delete(directory);
|
|
55
75
|
}
|
|
56
|
-
return await action
|
|
76
|
+
return await withToolLock(directory, 'ghidra', action, c.signal);
|
|
57
77
|
}
|
|
58
78
|
finally {
|
|
59
79
|
this.runtimeChanging.delete(directory);
|
|
@@ -78,7 +98,7 @@ class Owner {
|
|
|
78
98
|
const backend = async () => {
|
|
79
99
|
if (!selected.backend)
|
|
80
100
|
selected.backend = Promise.resolve(this.options.backend ?
|
|
81
|
-
this.options.backend(selected.workspace, c) : nativeInputs(c.profile.values, selected.workspace.directory).then(inputs => new GhidraContexts(selected.workspace, inputs, c)))
|
|
101
|
+
this.options.backend(selected.workspace, c) : nativeInputs(c.profile.values, selected.workspace.directory, c).then(inputs => new GhidraContexts(selected.workspace, inputs, c)))
|
|
82
102
|
.catch(error => { selected.backend = undefined; throw error; });
|
|
83
103
|
const result = await selected.backend;
|
|
84
104
|
if (result instanceof GhidraContexts)
|
|
@@ -96,6 +116,10 @@ class Owner {
|
|
|
96
116
|
const directory = app.AppDataDirectory, profile = this.profiles.get(directory);
|
|
97
117
|
if (this.runtimeChanging.has(directory))
|
|
98
118
|
fail('busy', 'Runtime preparation is in progress; finish it before changing or deleting the profile.');
|
|
119
|
+
if (toolProfileBusy(directory))
|
|
120
|
+
fail('busy', 'A tool operation is active.');
|
|
121
|
+
if ((await listProcesses(directory)).some(r => !['exited', 'failed'].includes(r.state)))
|
|
122
|
+
fail('busy', 'The profile has active or unverified tool processes.');
|
|
99
123
|
const materials = await readdir(join(directory, 'materials')).catch(error => { if (error.code === 'ENOENT')
|
|
100
124
|
return []; throw error; });
|
|
101
125
|
if (existsSync(join(directory, 'workspace', 'workspace.sqlite')) || materials.length)
|
|
@@ -198,6 +222,17 @@ function scopedFailures(entry, owner, parents = []) {
|
|
|
198
222
|
if (!selected)
|
|
199
223
|
return await run(input, c);
|
|
200
224
|
const services = owner.selected(c);
|
|
225
|
+
// First open of an already known target reserves its context inside Research.open.
|
|
226
|
+
// Existing contexts still use the command boundary to order automatic sync phases.
|
|
227
|
+
if (path[1] === 'open')
|
|
228
|
+
try {
|
|
229
|
+
services.workspace.context(selected);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
if (error instanceof CliError && error.code === 'coordinator.notFound')
|
|
233
|
+
return await run(input, c);
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
201
236
|
return await services.research.boundary(selected, async () => {
|
|
202
237
|
const excluded = ['open', 'merge', 'refresh', 'sync-policy', 'close', 'changes', 'debugger', 'ui', 'version-tracking', 'archive', 'projects', 'repository', 'server', 'formats', 'libraries', 'plugins'];
|
|
203
238
|
const eligible = entry.permission !== Permission.ReadOnly && entry.permission !== undefined && !excluded.includes(path[1]) && !['ghidra types archive-export', 'ghidra documentation transfer'].includes(name);
|
|
@@ -222,7 +257,7 @@ function scopedFailures(entry, owner, parents = []) {
|
|
|
222
257
|
export function createDefinition(options = {}) {
|
|
223
258
|
const owner = new Owner(options);
|
|
224
259
|
const definition = {
|
|
225
|
-
name: 'insight-cli', applicationId: 'insight-cli', version:
|
|
260
|
+
name: 'insight-cli', applicationId: 'insight-cli', version: packageVersion, description: 'Isolated research contexts and coordinated Ghidra analysis',
|
|
226
261
|
resources: [owner], permissions: { categories: [{ name: 'Destructive', description: 'Explicit deletion or replacement of retained research data', enabledByDefault: false }] }, ...(options.runtime ? { runtime: options.runtime } : {}),
|
|
227
262
|
profile: { fields: fields.map(([name, flags, description]) => ({ name: name, flags: flags, description: description,
|
|
228
263
|
...(name === 'maxContexts' ? { normalize: (value) => number(value, 16, 1) } : {}) })) },
|
|
@@ -277,15 +312,25 @@ export function createDefinition(options = {}) {
|
|
|
277
312
|
await c.secrets.delete('publisherPassword');
|
|
278
313
|
},
|
|
279
314
|
},
|
|
280
|
-
builtins: [
|
|
281
|
-
const name = args.name === undefined ? 'insight-cli' : text(args.name);
|
|
282
|
-
if (!['insight-cli', 'insight-re'].includes(name))
|
|
283
|
-
fail('notFound', 'Unknown skill; choose insight-cli or insight-re.');
|
|
284
|
-
return { version: '0.2.0', name, path: fileURLToPath(new URL(name === 'insight-re' ? '../../skills/insight-re/SKILL.md' : '../../SKILL.md', import.meta.url)),
|
|
285
|
-
skills: ['insight-cli', 'insight-re'] };
|
|
286
|
-
})],
|
|
315
|
+
builtins: [skillCommand()],
|
|
287
316
|
commands: [
|
|
288
317
|
...artifactsCommands(),
|
|
318
|
+
...diagnosticsCommands(c => owner.selected(c).workspace),
|
|
319
|
+
...llvmCommands(c => owner.selected(c).workspace),
|
|
320
|
+
...dieCommands(c => owner.selected(c).workspace),
|
|
321
|
+
...lldbCommands(c => owner.selected(c).workspace),
|
|
322
|
+
...windbgCommands(c => owner.selected(c).workspace),
|
|
323
|
+
...procmonCommands(),
|
|
324
|
+
...dnspyCommands(c => owner.selected(c).workspace),
|
|
325
|
+
...tsharkCommands(c => owner.selected(c).workspace),
|
|
326
|
+
...mitmproxyCommands(c => owner.selected(c).workspace),
|
|
327
|
+
...straceCommands(c => owner.selected(c).workspace),
|
|
328
|
+
...fridaCommands(c => owner.selected(c).workspace),
|
|
329
|
+
...sevenzipCommands(c => owner.selected(c).workspace),
|
|
330
|
+
...ilspyCommands(c => owner.selected(c).workspace),
|
|
331
|
+
...binaryCommands(c => owner.selected(c).workspace),
|
|
332
|
+
...captureCommands(c => owner.selected(c).workspace),
|
|
333
|
+
...toolProcessCommands({ ghidra: ghidraProcessHooks(c => owner.selected(c).workspace, (scope, c) => owner.selected(c).lifecycle.change(scope, 'close')) }, toolboxCommands()),
|
|
289
334
|
command('targets', 'Inspect immutable inputs', [
|
|
290
335
|
command('add <input>', 'Consume input without starting a tool', async ({ args }, c) => targetView(await owner.selected(c).workspace.importTarget(resolve(c.cwd, text(args.input, 4096)))), { permission: Permission.Update }),
|
|
291
336
|
command('list', 'List known inputs', ({ options: o }, c) => {
|
|
@@ -392,7 +437,7 @@ export function createDefinition(options = {}) {
|
|
|
392
437
|
}, { permission: Permission.Update, options: [...scoped, at, { flags: '--prototype <signature>', description: 'Complete C prototype', required: true },
|
|
393
438
|
{ flags: '--calling-convention <name>', description: 'Explicit convention supported by the selected compiler specification' }, request] }),
|
|
394
439
|
command('get', 'Read a function and entry comments', ({ options: o }, c) => owner.selected(c).research.function(scope(o), address(o.address)), { permission: Permission.ReadOnly, options: [...scoped, at] }),
|
|
395
|
-
command('decompile', 'Read decompiled function
|
|
440
|
+
command('decompile', 'Read a bounded Unicode window of one decompiled function', ({ options: o }, c) => owner.selected(c).research.function(scope(o), address(o.address), true, { limit: number(o.limitChars ?? 16000, 32768, 1), offset: number(o.offsetChars ?? 0, 4 * 1024 ** 2) }), { permission: Permission.ReadOnly, options: [...scoped, at, { flags: '--limit-chars <count>', description: 'Return 1–32768 Unicode characters', defaultValue: 16000 }, { flags: '--offset-chars <count>', description: 'Skip Unicode characters in the returned native text', defaultValue: 0 }] }),
|
|
396
441
|
command('rename', 'Record a saved private name', ({ options: o }, c) => {
|
|
397
442
|
const name = text(o.name, 512);
|
|
398
443
|
if (name !== name.trim())
|