pwn 0.5.729 → 0.5.732
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.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/documentation/Agent-Tool-Registry.md +1 -0
- data/documentation/Contributing.md +75 -0
- data/etc/default_skills/pwn/ai/agent/tools/mcp/SKILL.md +45 -0
- data/etc/default_skills/pwn/ai/mcp/SKILL.md +59 -0
- data/etc/default_skills/pwn/ai/mcp/combo_nation/SKILL.md +65 -0
- data/etc/default_skills/pwn/plugins/repl/SKILL.md +1 -0
- data/lib/pwn/ai/agent/tools/mcp.rb +40 -0
- data/lib/pwn/ai/mcp/combo_nation.rb +480 -0
- data/lib/pwn/ai/mcp.rb +377 -0
- data/lib/pwn/ai/tools/mcp.yaml +15 -0
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/plugins/repl.rb +140 -1
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/tools/mcp_spec.rb +70 -0
- data/spec/lib/pwn/ai/agent/verification_spec.rb +51 -9
- data/spec/lib/pwn/ai/mcp/combo_nation_spec.rb +215 -0
- data/spec/lib/pwn/ai/mcp_spec.rb +123 -0
- data/spec/lib/pwn/ffi/adalm_pluto_spec.rb +25 -11
- data/spec/lib/pwn/ffi/fftw_spec.rb +7 -2
- data/spec/lib/pwn/ffi/hack_rf_spec.rb +8 -2
- data/spec/lib/pwn/ffi/liquid_spec.rb +21 -5
- data/spec/lib/pwn/ffi/rtl_sdr_spec.rb +27 -4
- data/spec/lib/pwn/ffi/soapy_sdr_spec.rb +8 -2
- data/spec/lib/pwn/ffi/volk_spec.rb +10 -4
- data/spec/lib/pwn/plugins/binary_analysis_spec.rb +41 -11
- data/spec/lib/pwn/plugins/repl_spec.rb +55 -1
- data/spec/lib/pwn/sdr/decoder/dsp_spec.rb +40 -15
- data/spec/spec_helper.rb +7 -0
- data/third_party/pwn_rdoc.jsonl +51 -0
- metadata +17 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2cdd80d1b4ca26e89b583dbf7d8ad326f1a2a0d9217eabcf0856e57edfd2f80
|
|
4
|
+
data.tar.gz: 7dad008aa8906f6179687c13af204b60e6b8c7ae654cd82b6c6e033adeacef70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c56ac381842f7264fd01780860b2133a8b23364909cd80b0195758bdcec71d7785d6c7e7f6ed0ff9253d1bc689415b9979381daa8fd909533f1b81a1717cd644
|
|
7
|
+
data.tar.gz: 8dd6752b81448de9a92d173b56c5ddab6b50480faeb24a2442c6d3c03a450ae6f0d3e073eace4a7bf50d4301b39de8cff8e016f88054a9068fd5d5b68e7a74f2
|
data/Gemfile
CHANGED
|
@@ -50,9 +50,9 @@ gem 'libusb', '0.8.0'
|
|
|
50
50
|
gem 'luhn', '3.0.0'
|
|
51
51
|
gem 'mail', '2.9.1'
|
|
52
52
|
gem 'mcp', '1.5.1'
|
|
53
|
-
gem 'meshtastic', '0.0.
|
|
53
|
+
gem 'meshtastic', '0.0.178'
|
|
54
54
|
gem 'metasm', '1.0.6'
|
|
55
|
-
gem 'mongo', '2.
|
|
55
|
+
gem 'mongo', '2.26.0'
|
|
56
56
|
gem 'msfrpc-client', '1.1.2'
|
|
57
57
|
gem 'netaddr', '2.0.6'
|
|
58
58
|
gem 'net-ldap', '0.20.0'
|
|
@@ -81,7 +81,7 @@ gem 'rmagick', '7.1.4'
|
|
|
81
81
|
gem 'rqrcode', '3.2.0'
|
|
82
82
|
gem 'rspec', '3.13.2'
|
|
83
83
|
gem 'rtesseract', '3.1.4'
|
|
84
|
-
gem 'rubocop', '1.
|
|
84
|
+
gem 'rubocop', '1.91.0'
|
|
85
85
|
gem 'rubocop-rake', '0.7.1'
|
|
86
86
|
gem 'rubocop-rspec', '3.10.2'
|
|
87
87
|
gem 'ruby-audio', '1.6.1'
|
|
@@ -13,6 +13,7 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
|
|
|
13
13
|
| `http` | `http_proxy_start` · `http_proxy_stop` · `http_proxy_entries` · `http_proxy_rules` · `http_replay` | `PWN::Plugins::MitmProxy`: native HTTP HAR capture/replay; opaque CONNECT tunnels |
|
|
14
14
|
| `terminal` | `shell` | `Open3.capture3` on the host, after `PWN::AI::Agent::ToolGuard` |
|
|
15
15
|
| `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process, after `ToolGuard` |
|
|
16
|
+
| `mcp` | `mcp` | `PWN::AI::MCP` session broker → any `PWN::AI::MCP::*` stdio client |
|
|
16
17
|
| `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` · **`memory_lean`** | `PWN::Memory` → `~/.pwn/memory.json` |
|
|
17
18
|
| `skills` | `skills_consolidate` · **`skills_recall`** · `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` · `skill_migrate_legacy` | `~/.pwn/skills/<name>/SKILL.md` (**[agentskills.io](https://agentskills.io) spec**; legacy flat `*.md` auto-migrated) |
|
|
18
19
|
| `sessions` | **`session_recall`** · `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` · **`sessions_lean`** | `PWN::Sessions` → `~/.pwn/sessions/` |
|
|
@@ -60,6 +60,67 @@ An already-true `stop:` callback raises cancellation before spawning either clie
|
|
|
60
60
|
Invalid inputs still raise `ArgumentError`; native decoding never silently falls
|
|
61
61
|
back to another decoder or a detector.
|
|
62
62
|
|
|
63
|
+
### Optional Liquid and radare2 integration tests
|
|
64
|
+
|
|
65
|
+
Native Liquid DSP examples and the real radare2 JSON replay are also explicit
|
|
66
|
+
opt-ins, even when the backends happen to be installed. The default gate excludes
|
|
67
|
+
`liquid_integration` and `radare2_integration` metadata rather than marking tests
|
|
68
|
+
pending. Liquid interface checks, missing-library errors, pure-Ruby DSP fallback,
|
|
69
|
+
radare2 argument validation, and binutils fallback coverage still run by default.
|
|
70
|
+
The binary fallback tests require the existing binutils tools and `/bin/true`.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
PWN_TEST_LIQUID=1 bundle exec rspec spec/lib/pwn/ffi/liquid_spec.rb
|
|
74
|
+
PWN_TEST_RADARE2=1 bundle exec rspec spec/lib/pwn/plugins/binary_analysis_spec.rb
|
|
75
|
+
# Enable both in the full gate:
|
|
76
|
+
PWN_TEST_LIQUID=1 PWN_TEST_RADARE2=1 bundle exec rake
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Liquid opt-in requires the liquid-dsp shared library (`libliquid`) visible to the
|
|
80
|
+
dynamic loader. Radare2 opt-in requires `r2` and a C compiler named `cc` on PATH.
|
|
81
|
+
The radare2 example compiles a small unstripped C fixture in a temporary directory,
|
|
82
|
+
checks real JSON disassembly for its known `main` symbol, and removes the fixture
|
|
83
|
+
afterward. It does not assume the host's stripped `/bin/true` has a discoverable
|
|
84
|
+
`main`. Opt-in runs fail with installation guidance when a prerequisite is absent;
|
|
85
|
+
they never skip or accept a degraded backend as native success. The tests install
|
|
86
|
+
nothing and require no radio hardware or network access.
|
|
87
|
+
|
|
88
|
+
### Optional FFTW, Volk, and SDR shared-library tests
|
|
89
|
+
|
|
90
|
+
The default gate also excludes real FFTW/Volk computations and radio-library
|
|
91
|
+
integration checks, regardless of what is installed. Missing-library behavior,
|
|
92
|
+
mocked device inventory and stream lifecycle tests, and Ruby DSP fallbacks run
|
|
93
|
+
without these shared libraries and produce no pending examples.
|
|
94
|
+
|
|
95
|
+
| Environment opt-in | RSpec metadata | Loader prerequisite / coverage |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| `PWN_TEST_FFTW=1` | `fftw_integration` | `libfftw3f`; native impulse FFT |
|
|
98
|
+
| `PWN_TEST_VOLK=1` | `volk_integration` | `libvolk`; native conversion, accumulation, DSP dispatch |
|
|
99
|
+
| `PWN_TEST_RTL_SDR=1` | `rtl_sdr_integration` | `librtlsdr`; binding resolution only, no USB scan |
|
|
100
|
+
| `PWN_TEST_ADALM_PLUTO=1` | `adalm_pluto_integration` | Compatible `libiio`; library version only |
|
|
101
|
+
| `PWN_TEST_SOAPY_SDR=1` | `soapy_sdr_integration` | `libSoapySDR`; library/API version only |
|
|
102
|
+
| `PWN_TEST_HACK_RF=1` | `hack_rf_integration` | `libhackrf`; library version only |
|
|
103
|
+
|
|
104
|
+
For example:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
PWN_TEST_FFTW=1 bundle exec rspec spec/lib/pwn/ffi/fftw_spec.rb
|
|
108
|
+
PWN_TEST_VOLK=1 bundle exec rspec spec/lib/pwn/ffi/volk_spec.rb spec/lib/pwn/sdr/decoder/dsp_spec.rb
|
|
109
|
+
PWN_TEST_ADALM_PLUTO=1 bundle exec rspec spec/lib/pwn/ffi/adalm_pluto_spec.rb
|
|
110
|
+
PWN_TEST_LIQUID=1 bundle exec rspec spec/lib/pwn/ffi/liquid_spec.rb spec/lib/pwn/sdr/decoder/dsp_spec.rb
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Each opt-in fails with installation guidance if its library cannot load. Native
|
|
114
|
+
DSP integration tests assert real backend dispatch, not just a matching fallback.
|
|
115
|
+
None of these library opt-ins opens, tunes, receives from, or transmits through a
|
|
116
|
+
radio. Pluto URI discovery is mocked, including scan cleanup.
|
|
117
|
+
|
|
118
|
+
Actual RTL-SDR USB enumeration has a separate `rtl_sdr_hardware` tag, enabled
|
|
119
|
+
only by `PWN_TEST_RTL_SDR_HARDWARE=1`. It requires a connected RTL-SDR and USB
|
|
120
|
+
permissions, and fails on an empty inventory. Do not enable it in unattended
|
|
121
|
+
upgrade gates; library opt-ins do not enable hardware tests. It performs inventory
|
|
122
|
+
only, not tuning or reception. The test suite installs no dependencies.
|
|
123
|
+
|
|
63
124
|
## Adding a plugin
|
|
64
125
|
|
|
65
126
|
1. `lib/pwn/plugins/my_thing.rb` following the conventions above.
|
|
@@ -103,3 +164,17 @@ When you change code under `/opt/pwn`:
|
|
|
103
164
|
filler, no internal agent backlog codes).
|
|
104
165
|
|
|
105
166
|
Do not commit doc refreshes while lint or tests are still red.
|
|
167
|
+
|
|
168
|
+
### Optional combo.nation MCP integration tests
|
|
169
|
+
|
|
170
|
+
The default `bundle exec rake` does not launch `/opt/combo.nation/combo.nation`.
|
|
171
|
+
Protocol, menu-ID, and hardware-gate coverage uses an in-process fake MCP server.
|
|
172
|
+
The real stdio binary is excluded with `combo_nation_mcp` metadata unless:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
PWN_TEST_COMBO_NATION_MCP=1 bundle exec rspec spec/lib/pwn/ai/mcp/combo_nation_spec.rb
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
That opt-in never passes `--mcp-allow-hardware` and never opens devices. It fails
|
|
179
|
+
if the executable is missing rather than skipping pending.
|
|
180
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pwn-ai-agent-tools-mcp
|
|
3
|
+
description: Drive PWN::Ai::Agent::Tools::Mcp from pwn_eval.
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: [pwn, pwn_eval]
|
|
6
|
+
metadata:
|
|
7
|
+
bundled: true
|
|
8
|
+
generated: true
|
|
9
|
+
module: PWN::Ai::Agent::Tools::Mcp
|
|
10
|
+
source: pwn/ai/agent/tools/mcp.rb
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# PWN::Ai::Agent::Tools::Mcp
|
|
14
|
+
|
|
15
|
+
Public API for PWN::Ai::Agent::Tools::Mcp.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
Call `PWN::Ai::Agent::Tools::Mcp` from `pwn_eval` when the task needs this module.
|
|
20
|
+
Do not reimplement it in shell.
|
|
21
|
+
|
|
22
|
+
## Methodologies
|
|
23
|
+
|
|
24
|
+
Generated from `pwn/ai/agent/tools/mcp.rb`. Prefer the public class methods below.
|
|
25
|
+
Class methods take `(opts = {})` and read `opts`.
|
|
26
|
+
|
|
27
|
+
## How to call
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
PWN::Ai::Agent::Tools::Mcp.help
|
|
31
|
+
PWN::Ai::Agent::Tools::Mcp.help(opts)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Public methods
|
|
35
|
+
|
|
36
|
+
- _(no public class methods parsed)_
|
|
37
|
+
|
|
38
|
+
## Source
|
|
39
|
+
|
|
40
|
+
`pwn/ai/agent/tools/mcp.rb`
|
|
41
|
+
|
|
42
|
+
## Verification
|
|
43
|
+
|
|
44
|
+
`PWN::Ai::Agent::Tools::Mcp.respond_to?(:help)` after the
|
|
45
|
+
module is loaded. Read the source for parameter names.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pwn-ai-mcp
|
|
3
|
+
description: Drive PWN::AI::MCP from pwn_eval.
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: [pwn, pwn_eval]
|
|
6
|
+
metadata:
|
|
7
|
+
bundled: true
|
|
8
|
+
generated: true
|
|
9
|
+
module: PWN::AI::MCP
|
|
10
|
+
source: pwn/ai/mcp.rb
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# PWN::AI::MCP
|
|
14
|
+
|
|
15
|
+
Autoload MCP client modules that speak JSON-RPC 2.0 to local MCP servers. Session state lives here so pwn-ai Registry tools persist across turns.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
Call `PWN::AI::MCP` from `pwn_eval` when the task needs this module.
|
|
20
|
+
Do not reimplement it in shell.
|
|
21
|
+
|
|
22
|
+
## Methodologies
|
|
23
|
+
|
|
24
|
+
Generated from `pwn/ai/mcp.rb`. Prefer the public class methods below.
|
|
25
|
+
Class methods take `(opts = {})` and read `opts`.
|
|
26
|
+
|
|
27
|
+
## How to call
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
PWN::AI::MCP.help
|
|
31
|
+
PWN::AI::MCP.backends(opts)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Public methods
|
|
35
|
+
|
|
36
|
+
- `backends`
|
|
37
|
+
- `resolve`
|
|
38
|
+
- `use`
|
|
39
|
+
- `current`
|
|
40
|
+
- `connect`
|
|
41
|
+
- `disconnect`
|
|
42
|
+
- `ping`
|
|
43
|
+
- `list_tools`
|
|
44
|
+
- `call_tool`
|
|
45
|
+
- `poll_until`
|
|
46
|
+
- `invoke`
|
|
47
|
+
- `reset`
|
|
48
|
+
- `authors`
|
|
49
|
+
- `help`
|
|
50
|
+
- `reset!`
|
|
51
|
+
|
|
52
|
+
## Source
|
|
53
|
+
|
|
54
|
+
`pwn/ai/mcp.rb`
|
|
55
|
+
|
|
56
|
+
## Verification
|
|
57
|
+
|
|
58
|
+
`PWN::AI::MCP.respond_to?(:backends)` after the
|
|
59
|
+
module is loaded. Read the source for parameter names.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pwn-ai-mcp-combonation
|
|
3
|
+
description: Drive PWN::AI::MCP::ComboNation from pwn_eval.
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools: [pwn, pwn_eval]
|
|
6
|
+
metadata:
|
|
7
|
+
bundled: true
|
|
8
|
+
generated: true
|
|
9
|
+
module: PWN::AI::MCP::ComboNation
|
|
10
|
+
source: pwn/ai/mcp/combo_nation.rb
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# PWN::AI::MCP::ComboNation
|
|
14
|
+
|
|
15
|
+
JSON-RPC 2.0 / MCP 2024-11-05 stdio client for combo.nation. Speaks the native menu-oriented tools over newline-delimited JSON; it does not scrape a terminal or enable hardware unless requested.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
Call `PWN::AI::MCP::ComboNation` from `pwn_eval` when the task needs this module.
|
|
20
|
+
Do not reimplement it in shell.
|
|
21
|
+
|
|
22
|
+
## Methodologies
|
|
23
|
+
|
|
24
|
+
Generated from `pwn/ai/mcp/combo_nation.rb`. Prefer the public class methods below.
|
|
25
|
+
Class methods take `(opts = {})` and read `opts`.
|
|
26
|
+
|
|
27
|
+
## How to call
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
PWN::AI::MCP::ComboNation.help
|
|
31
|
+
PWN::AI::MCP::ComboNation.required_bins(opts)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Public methods
|
|
35
|
+
|
|
36
|
+
- `required_bins`
|
|
37
|
+
- `argv`
|
|
38
|
+
- `connect`
|
|
39
|
+
- `disconnect`
|
|
40
|
+
- `request`
|
|
41
|
+
- `notify`
|
|
42
|
+
- `ping`
|
|
43
|
+
- `list_tools`
|
|
44
|
+
- `call_tool`
|
|
45
|
+
- `menu_catalog`
|
|
46
|
+
- `menu_main`
|
|
47
|
+
- `menu_dial_calibration`
|
|
48
|
+
- `menu_guess`
|
|
49
|
+
- `hardware_connect`
|
|
50
|
+
- `operation_status`
|
|
51
|
+
- `operation_answer`
|
|
52
|
+
- `operation_cancel`
|
|
53
|
+
- `servo_pause`
|
|
54
|
+
- `poll_until`
|
|
55
|
+
- `authors`
|
|
56
|
+
- `help`
|
|
57
|
+
|
|
58
|
+
## Source
|
|
59
|
+
|
|
60
|
+
`pwn/ai/mcp/combo_nation.rb`
|
|
61
|
+
|
|
62
|
+
## Verification
|
|
63
|
+
|
|
64
|
+
`PWN::AI::MCP::ComboNation.respond_to?(:required_bins)` after the
|
|
65
|
+
module is loaded. Read the source for parameter names.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pwn/ai/agent/registry'
|
|
4
|
+
require 'pwn/ai/mcp'
|
|
5
|
+
|
|
6
|
+
PWN::AI::Agent::Registry.register(
|
|
7
|
+
name: 'mcp',
|
|
8
|
+
toolset: 'mcp',
|
|
9
|
+
schema: {
|
|
10
|
+
name: 'mcp',
|
|
11
|
+
description: 'Talk to local MCP servers through any PWN::AI::MCP::* client. ' \
|
|
12
|
+
'action=backends lists clients. action=use selects one. ' \
|
|
13
|
+
'connect/list_tools/call_tool/ping/status/disconnect operate on ' \
|
|
14
|
+
'that backend; session state persists across turns. ' \
|
|
15
|
+
'allow_hardware is connect-only and default false. ' \
|
|
16
|
+
'Pass tool arguments as a JSON object; keep string IDs as strings.',
|
|
17
|
+
parameters: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
action: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'backends | use | current | connect | disconnect | ping | list_tools | call_tool | poll_until | status'
|
|
23
|
+
},
|
|
24
|
+
backend: { type: 'string', description: 'Snake_case PWN::AI::MCP client name from action=backends.' },
|
|
25
|
+
session_id: { type: 'string', description: 'Optional session key. Defaults to the backend name.' },
|
|
26
|
+
name: { type: 'string', description: 'MCP tool name for call_tool, from list_tools on the selected backend.' },
|
|
27
|
+
arguments: { type: 'object', description: 'JSON object passed to tools/call. String IDs stay strings.' },
|
|
28
|
+
allow_hardware: { type: 'boolean', description: 'Only for connect. Default false. Never implied.' },
|
|
29
|
+
command: { type: 'string', description: 'Optional executable path for connect.' },
|
|
30
|
+
timeout: { type: 'integer', description: 'Seconds for handshake, reads, or poll_until.' },
|
|
31
|
+
states: { type: 'array', items: { type: 'string' }, description: 'poll_until terminal states if the backend implements it.' },
|
|
32
|
+
interval: { type: 'number', description: 'Seconds between poll_until status reads.' }
|
|
33
|
+
},
|
|
34
|
+
required: %w[action]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
handler: lambda { |args|
|
|
38
|
+
PWN::AI::MCP.invoke(args)
|
|
39
|
+
}
|
|
40
|
+
)
|