pwn 0.5.621 → 0.5.622

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.
@@ -16,7 +16,7 @@ module PWN
16
16
  #
17
17
  # Data flows:
18
18
  # Loop.run --(tool telemetry)--> Metrics.record
19
- # Loop.run --(final answer)----> Learning.auto_reflect (opt-in)
19
+ # Loop.run --(final answer)----> Learning.auto_introspect (opt-in)
20
20
  # model --(tool calls)------> learning_note_outcome / _distill_skill
21
21
  # PromptBuilder <----------------- Learning.to_context + Metrics.to_context
22
22
  #
@@ -164,9 +164,9 @@ module PWN
164
164
  # dry_run: 'optional - when true, do not write to Memory/Skills (default false)'
165
165
  # )
166
166
  #
167
- # Uses PWN::AI::Agent::Introspection (when available) to LLM-summarise the
167
+ # Uses PWN::AI::Agent::Reflect (when available) to LLM-summarise the
168
168
  # session into structured lessons. Falls back to a heuristic
169
- # extractor when introspection is disabled so learning never stops.
169
+ # extractor when module_reflection is disabled so learning never stops.
170
170
 
171
171
  public_class_method def self.reflect(opts = {})
172
172
  session_id = opts[:session_id]
@@ -193,19 +193,19 @@ module PWN
193
193
  end
194
194
 
195
195
  # Supported Method Parameters::
196
- # PWN::AI::Agent::Learning.auto_reflect(
196
+ # PWN::AI::Agent::Learning.auto_introspect(
197
197
  # session_id: 'required - id of the just-completed session',
198
198
  # request: 'optional - original user request (for outcome logging)',
199
199
  # final: 'optional - final assistant answer (for outcome logging)'
200
200
  # )
201
201
  #
202
- # Called by Loop.run when PWN::Env[:ai][:agent][:auto_reflect] is
202
+ # Called by Loop.run when PWN::Env[:ai][:agent][:auto_introspect] is
203
203
  # truthy. Never raises — learning must not break the primary loop.
204
204
 
205
- public_class_method def self.auto_reflect(opts = {})
205
+ public_class_method def self.auto_introspect(opts = {})
206
206
  session_id = opts[:session_id]
207
207
  return unless session_id
208
- return unless auto_reflect_enabled?
208
+ return unless auto_introspect_enabled?
209
209
 
210
210
  ok = infer_success(session_id: session_id, final: opts[:final])
211
211
  note_outcome(
@@ -218,7 +218,7 @@ module PWN
218
218
  reflect(session_id: session_id)
219
219
  Extrospection.auto_extrospect(session_id: session_id) if defined?(Extrospection)
220
220
  rescue StandardError => e
221
- warn "[pwn-ai/learning] auto_reflect swallowed: #{e.class}: #{e.message}"
221
+ warn "[pwn-ai/learning] auto_introspect swallowed: #{e.class}: #{e.message}"
222
222
  nil
223
223
  end
224
224
 
@@ -301,10 +301,10 @@ module PWN
301
301
  # privates
302
302
  # -------------------------------------------------------------
303
303
 
304
- private_class_method def self.auto_reflect_enabled?
304
+ private_class_method def self.auto_introspect_enabled?
305
305
  return false unless defined?(PWN::Env) && PWN::Env.is_a?(Hash)
306
306
 
307
- PWN::Env.dig(:ai, :agent, :auto_reflect) ? true : false
307
+ PWN::Env.dig(:ai, :agent, :auto_introspect) ? true : false
308
308
  rescue StandardError
309
309
  false
310
310
  end
@@ -314,7 +314,7 @@ module PWN
314
314
  # Derive a success signal stronger than "final answer non-empty":
315
315
  # look at the tool-failure ratio inside the just-completed turn AND
316
316
  # scan the final text for self-reported failure language. Without
317
- # this, auto_reflect logs ~100 % success and the negative-feedback
317
+ # this, auto_introspect logs ~100 % success and the negative-feedback
318
318
  # side of the learning loop never fires.
319
319
  private_class_method def self.infer_success(opts = {})
320
320
  final = opts[:final].to_s
@@ -353,11 +353,11 @@ module PWN
353
353
 
354
354
  private_class_method def self.introspective_lessons(opts = {})
355
355
  transcript = opts[:transcript] || []
356
- return [] unless defined?(PWN::AI::Agent::Introspection)
357
- return [] unless defined?(PWN::Env) && PWN::Env.is_a?(Hash) && PWN::Env.dig(:ai, :introspection)
356
+ return [] unless defined?(PWN::AI::Agent::Reflect)
357
+ return [] unless defined?(PWN::Env) && PWN::Env.is_a?(Hash) && PWN::Env.dig(:ai, :module_reflection)
358
358
 
359
359
  req = "Analyse this pwn-ai session transcript and emit up to 5 durable, generalizable lessons (one per line, no numbering, imperative voice) that would make future runs faster or more reliable. Focus on tool selection, error recovery, and target-agnostic technique. Ignore trivia.\n\nTRANSCRIPT:\n#{transcript_text(transcript: transcript)}"
360
- resp = PWN::AI::Agent::Introspection.reflect_on(request: req, suppress_pii_warning: true)
360
+ resp = PWN::AI::Agent::Reflect.on(request: req, suppress_pii_warning: true)
361
361
  resp.to_s.lines.map(&:strip).reject(&:empty?).first(5)
362
362
  rescue StandardError
363
363
  []
@@ -420,7 +420,7 @@ module PWN
420
420
  PWN::AI::Agent::Learning.note_outcome(task: 'nmap sweep 10.0.0.0/24', success: true, details: '12 hosts up')
421
421
  PWN::AI::Agent::Learning.outcomes(limit: 20, success: false)
422
422
  PWN::AI::Agent::Learning.reflect(session_id: sid) # LLM or heuristic → PWN::Memory
423
- PWN::AI::Agent::Learning.auto_reflect(session_id: sid, request: req, final: text)
423
+ PWN::AI::Agent::Learning.auto_introspect(session_id: sid, request: req, final: text)
424
424
  PWN::AI::Agent::Learning.distill_skill(name: 'quick_recon', session_id: sid)
425
425
  PWN::AI::Agent::Learning.consolidate(max_entries: 200) # dedupe + prune Memory
426
426
  PWN::AI::Agent::Learning.to_context(limit: 5) # injected by PromptBuilder
@@ -428,7 +428,7 @@ module PWN
428
428
  PWN::AI::Agent::Learning.reset
429
429
 
430
430
  Enable end-of-run auto-learning with:
431
- PWN::Env[:ai][:agent][:auto_reflect] = true
431
+ PWN::Env[:ai][:agent][:auto_introspect] = true
432
432
 
433
433
  #{self}.authors
434
434
  USAGE
@@ -241,7 +241,7 @@ module PWN
241
241
  if calls.empty?
242
242
  text = msg[:content].to_s
243
243
  append_session(session_id: session_id, role: 'assistant', content: text)
244
- Learning.auto_reflect(session_id: session_id, request: request, final: text) if defined?(Learning)
244
+ Learning.auto_introspect(session_id: session_id, request: request, final: text) if defined?(Learning)
245
245
  return text
246
246
  end
247
247
 
@@ -5,14 +5,14 @@ require 'json'
5
5
  module PWN
6
6
  module AI
7
7
  module Agent
8
- # PWN::AI::Agent::Introspection is the inward-facing counterpart to
8
+ # PWN::AI::Agent::Reflect is the inward-facing counterpart to
9
9
  # PWN::AI::Agent::Extrospection. Where Extrospection looks OUTWARD at
10
10
  # the world the agent operates in (host state, toolchain, network,
11
- # threat-intel), Introspection looks INWARD - it lets pwn hand a
12
- # request to the active AI engine and reflect on its own artifacts,
13
- # transcripts, findings, code, or decisions.
11
+ # threat-intel), Reflect looks INWARD - it lets pwn hand a request to
12
+ # the active AI engine and reflect on its own artifacts, transcripts,
13
+ # findings, code, or decisions.
14
14
  #
15
- # This module is gated by `PWN::Env[:ai][:introspection]` so that
15
+ # This module is gated by `PWN::Env[:ai][:module_reflection]` so that
16
16
  # potentially-sensitive local data is never shipped to a remote LLM
17
17
  # unless the operator has explicitly opted in via pwn-vault / config.
18
18
  #
@@ -21,16 +21,16 @@ module PWN
21
21
  # through when it wants an LLM opinion on locally-produced data, and
22
22
  # it is also what PWN::AI::Agent::Learning.reflect uses to distill
23
23
  # session transcripts into durable PWN::Memory lessons.
24
- module Introspection
24
+ module Reflect
25
25
  # Supported Method Parameters::
26
- # response = PWN::AI::Agent::Introspection.reflect_on(
26
+ # response = PWN::AI::Agent::Reflect.on(
27
27
  # request: 'required - String - What you want the AI to reflect on',
28
28
  # system_role_content: 'optional - context to set up the model behavior for reflection',
29
29
  # spinner: 'optional - Boolean - Display spinner during operation (default: false)',
30
30
  # suppress_pii_warning: 'optional - Boolean - Suppress PII Warnings (default: false)'
31
31
  # )
32
32
 
33
- public_class_method def self.reflect_on(opts = {})
33
+ public_class_method def self.on(opts = {})
34
34
  request = opts[:request]
35
35
  raise 'ERROR: request must be provided' if request.nil?
36
36
 
@@ -42,14 +42,14 @@ module PWN
42
42
 
43
43
  response = nil
44
44
 
45
- ai_introspection = PWN::Env[:ai][:introspection]
45
+ ai_module_reflection = PWN::Env[:ai][:module_reflection]
46
46
 
47
- if ai_introspection && request.length.positive?
47
+ if ai_module_reflection && request.length.positive?
48
48
  engine = PWN::Env[:ai][:active].to_s.downcase.to_sym
49
49
  valid_ai_engines = PWN::AI.help.reject { |e| e.downcase == :agent }.map(&:downcase)
50
50
  raise "ERROR: Unsupported AI engine. Supported engines are: #{valid_ai_engines}" unless valid_ai_engines.include?(engine)
51
51
 
52
- warn "AI Introspection is enabled. Ensure #{engine} has been authorized for use and/or requests are sanitized properly." unless suppress_pii_warning
52
+ warn "AI Reflection is enabled. Ensure #{engine} has been authorized for use and/or requests are sanitized properly." unless suppress_pii_warning
53
53
  response = PWN::AI::Agent::Loop.run(
54
54
  request: request.chomp,
55
55
  system_role_content: system_role_content,
@@ -75,7 +75,7 @@ module PWN
75
75
 
76
76
  public_class_method def self.help
77
77
  puts "USAGE:
78
- #{self}.reflect_on(
78
+ #{self}.on(
79
79
  request: 'required - String - What you want the AI to reflect on',
80
80
  system_role_content: 'optional - context to set up the model behavior for reflection',
81
81
  spinner: 'optional - Boolean - Display spinner during operation (default: false)',
@@ -16,7 +16,7 @@ module PWN
16
16
 
17
17
  system_role_content = 'Your sole purpose is to analyze source code snippets and generate an Exploit Prediction Scoring System (EPSS) score between 0% - 100%. Just generate a score unless score is >= 75% in which a PoC and code fix should also be included.'
18
18
 
19
- PWN::AI::Agent::Introspection.reflect_on(
19
+ PWN::AI::Agent::Reflect.on(
20
20
  system_role_content: system_role_content,
21
21
  request: request,
22
22
  suppress_pii_warning: true
@@ -258,7 +258,7 @@ PWN::AI::Agent::Registry.register(
258
258
  name: 'extro_auto_toggle',
259
259
  description: 'Enable/disable end-of-run auto-extrospection ' \
260
260
  '(PWN::Env[:ai][:agent][:auto_extrospect]). When enabled, ' \
261
- 'Learning.auto_reflect ALSO calls Extrospection.auto_' \
261
+ 'Learning.auto_introspect ALSO calls Extrospection.auto_' \
262
262
  'extrospect after every final answer, so host drift is ' \
263
263
  'captured continuously without an explicit extro_snapshot ' \
264
264
  'call. Omit `enabled` to just read the current state.',
@@ -190,13 +190,13 @@ PWN::AI::Agent::Registry.register(
190
190
  )
191
191
 
192
192
  PWN::AI::Agent::Registry.register(
193
- name: 'learning_auto_reflect_toggle',
193
+ name: 'learning_auto_introspect_toggle',
194
194
  toolset: 'learning',
195
195
  schema: {
196
- name: 'learning_auto_reflect_toggle',
196
+ name: 'learning_auto_introspect_toggle',
197
197
  description: 'Enable/disable end-of-run auto-reflection ' \
198
- '(PWN::Env[:ai][:agent][:auto_reflect]). When enabled, ' \
199
- 'Loop.run calls Learning.auto_reflect on the session after ' \
198
+ '(PWN::Env[:ai][:agent][:auto_introspect]). When enabled, ' \
199
+ 'Loop.run calls Learning.auto_introspect on the session after ' \
200
200
  'every final answer. Disable during noisy fuzzing loops; ' \
201
201
  're-enable for the summary turn. Omit `enabled` to just ' \
202
202
  'read the current state.',
@@ -214,8 +214,8 @@ PWN::AI::Agent::Registry.register(
214
214
  raise 'PWN::Env[:ai] is unavailable or immutable' unless ai.is_a?(Hash) && !ai.frozen?
215
215
 
216
216
  ai[:agent] = (ai[:agent] || {}).dup if ai[:agent].nil? || ai[:agent].frozen?
217
- prev = ai[:agent][:auto_reflect] ? true : false
218
- ai[:agent][:auto_reflect] = (args[:enabled] ? true : false) if args.key?(:enabled)
219
- { previous: prev, current: ai[:agent][:auto_reflect] ? true : false }
217
+ prev = ai[:agent][:auto_introspect] ? true : false
218
+ ai[:agent][:auto_introspect] = (args[:enabled] ? true : false) if args.key?(:enabled)
219
+ { previous: prev, current: ai[:agent][:auto_introspect] ? true : false }
220
220
  }
221
221
  )
@@ -20,7 +20,7 @@ module PWN
20
20
 
21
21
  system_role_content = "Being an expert penetration tester skilled in code analysis, debugging, and exploitation while stepping through JavaScript in a Chrome DevTools debugging session: 1. Your sole purpose is to analyze each JavaScript step and generate an Exploit Prediction Scoring System (EPSS) score between 0% - 100%. The step currently resides in this block of JavaScript:\n```\n#{source_to_review}\n```\n2. If the score is >= 75%, generate a JavaScript proof-of-concept that would allow a threat actor to directly exploit or target a user for exploitation (i.e. no self-exploit). 3. If the EPSS score is >= 75% also provide a code fix. *** If the EPSS score is < 75%, no explanations or summaries - just the EPSS score."
22
22
 
23
- PWN::AI::Agent::Introspection.reflect_on(
23
+ PWN::AI::Agent::Reflect.on(
24
24
  system_role_content: system_role_content,
25
25
  request: request,
26
26
  suppress_pii_warning: true
@@ -12,7 +12,7 @@ module PWN
12
12
  # 4. CVSS score, vector string, and first.org calculator URI
13
13
  # 5. CWE category, brief description, and CWE URI
14
14
  # 6. Relevant NIST 800-53 control
15
- # It leverages the PWN::AI::Agent::Introspection.reflect_on method. Defaults to Jira for existing workflow compatibility.
15
+ # It leverages the PWN::AI::Agent::Reflect.on method. Defaults to Jira for existing workflow compatibility.
16
16
  module VulnGen
17
17
  # Supported Method Parameters::
18
18
  # ai_analysis = PWN::AI::Agent::VulnGen.analyze(
@@ -60,7 +60,7 @@ module PWN
60
60
  6. NIST 800-53 Security Control that is impacted by this vulnerability.
61
61
  "
62
62
 
63
- analysis = PWN::AI::Agent::Introspection.reflect_on(
63
+ analysis = PWN::AI::Agent::Reflect.on(
64
64
  system_role_content: system_role_content,
65
65
  request: request,
66
66
  suppress_pii_warning: true
data/lib/pwn/ai/agent.rb CHANGED
@@ -27,7 +27,7 @@ module PWN
27
27
  autoload :Learning, 'pwn/ai/agent/learning'
28
28
  autoload :Mistakes, 'pwn/ai/agent/mistakes'
29
29
  autoload :Extrospection, 'pwn/ai/agent/extrospection'
30
- autoload :Introspection, 'pwn/ai/agent/introspection'
30
+ autoload :Reflect, 'pwn/ai/agent/reflect'
31
31
  autoload :Swarm, 'pwn/ai/agent/swarm'
32
32
 
33
33
  # Display a List of Every PWN::AI Module
@@ -250,17 +250,21 @@ module PWN
250
250
  end
251
251
  messages.push(user_role)
252
252
 
253
- # `max_tokens` is deprecated on /v1/chat/completions; the unified
254
- # parameter is `max_completion_tokens` and works for every chat model
253
+ # Wire config key `max_tokens` (kept for cross-engine naming parity with
254
+ # Anthropic/Gemini) to the OpenAI wire-format field `max_completion_tokens`.
255
+ # OpenAI deprecated the request-body key `max_tokens` on /v1/chat/completions
256
+ # in favour of `max_completion_tokens`, which works for every chat model
255
257
  # including the reasoning family. Don't try to guess per-model caps —
256
- # let the server clamp; default to a generous ceiling that the
257
- # operator can override via PWN::Env[:ai][:openai][:max_completion_tokens].
258
- max_completion_tokens = (engine[:max_completion_tokens] || 16_384).to_i
258
+ # let the server clamp; default to a generous ceiling that the operator
259
+ # can override via PWN::Env[:ai][:openai][:max_tokens].
260
+ # Accept legacy :max_completion_tokens as a one-release alias so existing
261
+ # pwn.yaml files keep working without a silent clamp to the default.
262
+ max_tokens = (engine[:max_tokens] || engine[:max_completion_tokens] || 16_384).to_i
259
263
 
260
264
  http_body = {
261
265
  model: model,
262
266
  messages: messages,
263
- max_completion_tokens: max_completion_tokens
267
+ max_completion_tokens: max_tokens
264
268
  }
265
269
  # Reasoning models reject sampler params (temperature, top_p, etc.)
266
270
  http_body[:temperature] = temp unless reasoning
data/lib/pwn/config.rb CHANGED
@@ -29,7 +29,7 @@ module PWN
29
29
  env = {
30
30
  ai: {
31
31
  active: 'grok',
32
- introspection: false,
32
+ module_reflection: false,
33
33
  grok: {
34
34
  base_uri: 'optional - Base URI for Grok - Use private base OR defaults to https://api.x.ai/v1',
35
35
  key: 'required - xAI Grok API Key',
@@ -58,6 +58,7 @@ module PWN
58
58
  model: 'optional - OpenAI model to use',
59
59
  system_role_content: 'You are an ethically hacking OpenAI agent.',
60
60
  temp: 'optional - OpenAI temperature',
61
+ max_tokens: 'optional - Max output tokens per response (default 16384). Mapped to OpenAI wire param max_completion_tokens.',
61
62
  max_prompt_length: 128_000
62
63
  },
63
64
  ollama: {
@@ -90,9 +91,9 @@ module PWN
90
91
  max_iters: 25,
91
92
  # Swarm (agent_ask/agent_debate) sub-agent recursion cap
92
93
  max_depth: 3,
93
- # run PWN::AI::Agent::Learning.auto_reflect after every final answer
94
- auto_reflect: true,
95
- # also run PWN::AI::Agent::Extrospection.auto_extrospect from auto_reflect
94
+ # run PWN::AI::Agent::Learning.auto_introspect after every final answer
95
+ auto_introspect: true,
96
+ # also run PWN::AI::Agent::Extrospection.auto_extrospect from auto_introspect
96
97
  auto_extrospect: false,
97
98
  toolsets: nil
98
99
  # multi-agent personas : ~/.pwn/agents.yml (see PWN::AI::Agent::Swarm.help)
@@ -50,7 +50,7 @@ module PWN
50
50
  # type: 'required - type of history to introspect (:sitemap, :proxy_history, :websocket_history)'
51
51
  # )
52
52
  private_class_method def self.init_introspection_thread(opts = {})
53
- # if PWN::Env[:ai][:introspection] is true,
53
+ # if PWN::Env[:ai][:module_reflection] is true,
54
54
  # spin up Thread to:
55
55
  # 1. Periodically call get_proxy_history(burp_obj: burp_obj) method
56
56
  # 2. For each entry w/ empty comment,
@@ -65,7 +65,7 @@ module PWN
65
65
  type = opts[:type]
66
66
  raise "ERROR: type parameter is required and must be one of: #{valid_types.join(', ')}" unless valid_types.include?(type)
67
67
 
68
- if PWN::Env[:ai][:introspection]
68
+ if PWN::Env[:ai][:module_reflection]
69
69
  introspection_thread_arr = burp_obj[:introspection_threads] ||= []
70
70
  introspection_thread = Thread.new do
71
71
  get_highlight_color = lambda do |opts = {}|
@@ -19,8 +19,8 @@ module PWN
19
19
  dir_path = opts[:dir_path]
20
20
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
21
21
  result_arr = []
22
- ai_introspection = PWN::Env[:ai][:introspection]
23
- logger_results = "AI Introspection => #{PWN::Env[:ai][:introspecction]} => "
22
+ ai_module_reflection = PWN::Env[:ai][:module_reflection]
23
+ logger_results = "AI Module Reflection => #{PWN::Env[:ai][:module_reflection]} => "
24
24
 
25
25
  PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
26
26
  if File.file?(entry) && File.basename(entry) == 'pom.xml' && entry !~ /test/i
@@ -63,7 +63,7 @@ module PWN
63
63
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
64
64
 
65
65
  result_arr = []
66
- logger_results = "AI Introspection => #{PWN::Env[:ai][:introspection]} => "
66
+ logger_results = "AI Module Reflection => #{PWN::Env[:ai][:module_reflection]} => "
67
67
 
68
68
  PWN::Plugins::FileFu.recurse_in_dir(
69
69
  dir_path: dir_path,
data/lib/pwn/sdr/gqrx.rb CHANGED
@@ -809,7 +809,7 @@ module PWN
809
809
  puts "\s\s- A lower `Input rate` value seems counter-intuitive but works well (e.g. ADALM PLUTO ~ 1000000)."
810
810
  puts '2. Adjust the :strength_lock parameter.'
811
811
  puts '3. Adjust the :precision parameter.'
812
- puts '4. Disable AI introspection in PWN::Env'
812
+ puts '4. Disable AI module_reflection in PWN::Env'
813
813
  puts 'Happy scanning!'
814
814
  puts '-' * 86
815
815
  # print 'Pressing ENTER to begin scan...'
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.621'
4
+ VERSION = '0.5.622'
5
5
  end
@@ -2,14 +2,14 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe PWN::AI::Agent::Introspection do
5
+ describe PWN::AI::Agent::Reflect do
6
6
  it 'should display information for authors' do
7
- authors_response = PWN::AI::Agent::Introspection
7
+ authors_response = PWN::AI::Agent::Reflect
8
8
  expect(authors_response).to respond_to :authors
9
9
  end
10
10
 
11
11
  it 'should display information for existing help method' do
12
- help_response = PWN::AI::Agent::Introspection
12
+ help_response = PWN::AI::Agent::Reflect
13
13
  expect(help_response).to respond_to :help
14
14
  end
15
15
  end